ไวยากรณ์การประกาศฟังก์ชัน: สิ่งต่าง ๆ ในวงเล็บก่อนชื่อฟังก์ชัน


249

ฉันขอโทษฉันไม่สามารถเจาะจงมากขึ้นในชื่อคำถาม แต่ฉันอ่านรหัสGoบางส่วนและฉันพบการประกาศฟังก์ชันของแบบฟอร์มนี้

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    ...
}

จากhttps://github.com/mattermost/platform/blob/master/api/context.go

func (s *GracefulServer) BlockingClose() bool {
    ...
}

จากhttps://github.com/braintree/manners/blob/master/server.go

อะไร(h handler)และ(s *GracefulServer)ระหว่างวงเล็บหมายถึง? การประกาศฟังก์ชันทั้งหมดหมายความว่าอย่างไรโดยคำนึงถึงความหมายของสิ่งต่าง ๆ ระหว่างวงเล็บ?

แก้ไข

นี่ไม่ใช่ความซ้ำซ้อนของฟังก์ชั่นและวิธีการใน Go? : คำถามนี้มาถึงฉันเพราะฉันไม่ทราบว่าสิ่งที่อยู่ในวงเล็บก่อนที่ชื่อฟังก์ชั่นไม่ได้เพราะฉันสงสัยว่าสิ่งที่แตกต่างระหว่างฟังก์ชั่นและวิธีการ ... ถ้าฉันรู้ว่าประกาศนี้เป็นวิธีที่ฉันจะไม่ ไม่มีคำถามนี้ในตอนแรก ถ้ามีคนสงสัยฉันเหมือนกันสักวันฉันไม่เชื่อว่าเธอจะไปหา "วิธีการแบบโกลาน" เพราะเธอไม่รู้ว่านี่เป็นกรณี มันก็เหมือนกับการสงสัยว่าตัวอักษร "sigma" หมายถึงก่อนการแสดงออกทางคณิตศาสตร์ (ไม่รู้ว่ามันหมายถึงการรวมกัน) และมีคนบอกว่ามันเป็นสำเนาของความแตกต่างระหว่างการรวมและสิ่งอื่น ๆ

นอกจากนี้คำตอบสั้น ๆ สำหรับคำถามนี้ ("เป็นผู้รับ") คือไม่มีคำตอบว่า "อะไรคือความแตกต่างระหว่างฟังก์ชั่นและวิธีการ"


27
@Volker จากนั้นแจ้งว่าคำว่า Go Go บน stackoverflow ตอบคำถามที่ไม่ได้อยู่ใน Tour of Go เท่านั้น ในชุมชน Haskell ผู้คนสามารถถามคำถามเช่นฉันจะขอnองค์ประกอบที่ได้จากรายการใน Haskell ได้อย่างไร ซึ่งอยู่ในบทนำเกี่ยวกับเรียนรู้คุณ Haskell เพื่อความดีที่ยิ่งใหญ่และรับคำถามของพวกเขาตอบโดยไม่ต้องกังวลเกี่ยวกับมัน
Marcus Vinícius Monteiro

23
เมื่อฉันมีคำถามนี้ฉันไปทัวร์ครั้งแรก ฉันตรวจสอบชื่อ "ฟังก์ชั่น" ทั้งหมดและไม่มีตัวอย่างใดครอบคลุมถึงเรื่องนี้ tour.golang.org/basics/4 tour.golang.org/basics/5หากคุณไม่ทราบว่าจะขยายวิธีการและอินเทอร์เฟซคุณจะไม่เห็นชื่อเรื่อง คำถามนี้ถูกต้องและดีเยี่ยมสำหรับการจัดทำดัชนีของ Google Zealots ธงที่ซ้ำกันต้องเบาขึ้น
Bruno Bronosky

14
ขอบคุณที่ไม่เจาะจงในคำถามของคุณเพราะมันเพียงพอที่จะช่วยฉันค้นหาคำตอบ!
David K

1
คุณถามสิ่งที่ฉันค้นหาอย่างแม่นยำมันเป็นคำถามที่ถูกต้อง ขอบคุณ. ฉันอ่านนิยามฟังก์ชั่นทุกชนิดและไม่มีใครอธิบายสิ่งนี้ ฉันยังคงพยายามเขียนคำถามของฉันและพบสิ่งนี้
Ajak6

คำตอบ:


200

สิ่งนี้เรียกว่า 'ผู้รับ' ในกรณีแรก(h handler)มันเป็นประเภทค่าในครั้งที่สอง(s *GracefulServer)มันเป็นตัวชี้ วิธีการทำงานใน Go อาจแตกต่างจากภาษาอื่นบ้างเล็กน้อย ประเภทการรับอย่างไรก็ตามทำงานได้มากหรือน้อยเหมือนคลาสในการเขียนโปรแกรมเชิงวัตถุส่วนใหญ่ มันเป็นสิ่งที่คุณเรียกใช้เมธอดเหมือนถ้าฉันใส่วิธีลงAในคลาสบางคลาสPersonแล้วฉันจะต้องการอินสแตนซ์ของประเภทPersonเพื่อที่จะเรียกใช้A(สมมติว่ามันเป็นวิธีการแบบอินสแตนซ์

หนึ่ง gotcha ที่นี่เป็นที่รับสัญญาณที่ได้รับการผลักดันเข้าสู่การเรียกกองเหมือนข้อโต้แย้งอื่น ๆ ดังนั้นหากรับเป็นประเภทค่าเช่นในกรณีของhandlerคุณแล้วคุณจะได้ทำงานกับสำเนาของสิ่งที่คุณเรียกว่าวิธีการจากความหมายบางอย่างเช่นh.Name = "Evan"หากว่า ไม่คงอยู่หลังจากคุณกลับสู่ขอบเขตการโทร ด้วยเหตุผลนี้ทุกสิ่งที่คาดว่าจะเปลี่ยนสถานะของผู้รับต้องใช้ตัวชี้หรือส่งคืนค่าที่แก้ไข (ให้กระบวนทัศน์ประเภทที่ไม่เปลี่ยนรูปมากขึ้นหากคุณกำลังมองหา)

นี่คือส่วนที่เกี่ยวข้องจากสเป็ค; https://golang.org/ref/spec#Method_sets


6
คำอธิบายที่ดีและคะแนนกรรมพิเศษสำหรับการเชื่อมโยงไปยังข้อมูลจำเพาะที่เกี่ยวข้อง
Marius Waldal

4
ทัวร์ golang มีตัวอย่างที่มีประโยชน์และน่าสนใจเช่นกันtour.golang.org/methods/1
tw_hoff

90

มันหมายความว่าServeHTTPไม่ใช่ฟังก์ชั่นแบบสแตนด์อโลน วงเล็บข้างหน้าชื่อฟังก์ชันคือวิธีการกำหนดวัตถุที่ฟังก์ชันเหล่านี้จะทำงาน ดังนั้นโดยพื้นฐานแล้วServeHTTPเป็นวิธีการจัดการประเภทและสามารถเรียกใช้โดยใช้วัตถุใด ๆ พูดว่า h ของการจัดการประเภท

h.ServeHTTP(w, r)

พวกเขาจะเรียกว่ารับ มีสองวิธีในการกำหนดพวกเขา หากคุณต้องการแก้ไขตัวรับให้ใช้ตัวชี้ดังนี้:

func (s *MyStruct) pointerMethod() { } // method on pointer

หากคุณไม่ต้องการแก้ไขผู้รับคุณสามารถกำหนดผู้รับเป็นค่าเช่น:

func (s MyStruct)  valueMethod()   { } // method on value

ตัวอย่างนี้จากสนามเด็กเล่นไปแสดงให้เห็นถึงแนวคิด

package main

import "fmt"

type Mutatable struct {
    a int
    b int
}

func (m Mutatable) StayTheSame() {
    m.a = 5
    m.b = 7
}

func (m *Mutatable) Mutate() {
    m.a = 5
    m.b = 7
}

func main() {
    m := &Mutatable{0, 0}
    fmt.Println(m)
    m.StayTheSame()
    fmt.Println(m)
    m.Mutate()
    fmt.Println(m)

ผลลัพธ์ของโปรแกรมข้างต้นคือ:

&{0 0}
&{0 0}
&{5 7}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.