<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
//func關鍵字 //getStudent函數名 //(id int, classId int) 參數列 //(name string,age int) 返回值列表 func getStudent(id int, classId int)(name string,age int) { //函數體 if id==1&&classId==1{ name = "BigOrange" age = 26 } //返回值 return name, age // 支援多重返回值 }
有意思的是Go語言的返回值可以有多個,並且放在了參數列後面,而C#等都是在函數名之前,也沒有關鍵字。
import "fmt" //呼叫fmt包中的Println方法。 fmt.Println("Name:", std.Name, "Age:",std.Age)
很好奇為什麼沒有public private等關鍵字,那函數怎麼才能定義為公用和私有呢?
Go語言有這樣的規則:小寫字母開頭的函數只在本包內可見,大寫字母開頭的函數才
能被其他包使用。這個規則也適用於型別和變數的可見性。
不定引數是指函數傳入的引數個數為不定數量。
func myfunc(args ...int) { for _, arg := range args { fmt.Println(arg) } }
函數myfunc()接受不定數量的引數,這些引數的型別全部是int
※形如...type格式的型別只能作為函數的引數型別存在,並且必須是最後一個引數。
它是一個語法糖(syntactic sugar),即這種語法對語言的功能並沒有影響,但是更方便程式設計師使用。
從內部實現機理上來說,型別...type本質上是一個陣列切片,也就是[]type,這也是為
什麼上面的引數args可以用for迴圈來獲得每個傳入的引數。
不定引數的傳遞
myfunc3(args ...int)
對應上面的這個函數,傳遞引數可以為下面兩種
// 按原樣傳遞 myfunc3(args...) // 傳遞片段,實際上任意的int slice都可以傳進去 myfunc3(args[1:]...)
任意型別的不定引數
可以看到 fmt.Println()方法接受了不定引數,但它是 ...interface{}
用interface{}傳遞任意型別資料是Go語言的慣例用法。
Go語言函數可以返回多個返回值
如果呼叫方呼叫了一個具有多返回值的方法,但是卻不想關心其中的某個返回值,可以簡單
地用一個下劃線“_”來跳過這個返回值
Go語言支援隨時在程式碼裡定義匿名函數。
匿名函數由一個不帶函數名的函數宣告和函數體組成
func(a, b int, z float64) bool { return a*b <int(z) }
匿名函數可以直接賦值給一個變數或者直接執行:(有點像js哈)
f := func(x, y int) int { return x + y }
func(ch chan int) { ch <- ACK } (reply_chan) // 花括號後直接跟參數列表示函數呼叫
package main import ( "fmt" ) func main() { var j int = 5 a := func()(func()) { var i int = 10 return func() { fmt.Printf("i, j: %d, %dn", i, j) } }() a() j *= 2 a() }
結果:
i, j: 10, 5
i, j: 10, 10
1---"...func()(func()) {....."
表明此匿名函數返回值的型別是func(), 即此匿名函數返回一個函數指標(此處參照一下c 的概念);
2---"...returnfunc() {
fmt.Printf("i, j: %d, %dn", i, j)
}..."
表明返回的函數指標指向一個列印i, j: %d, %dn的函數;
3---"...a := func()(func()) {
...
}()..."
末尾的括號表明匿名函數被呼叫,並將返回的函數指標賦給變數a ;
綜合來看:
"...a := func()(func()) { var i int = 10 return func() { fmt.Printf("i, j: %d, %dn", i, j) } }()..."
此程式碼片段的意思"等價於"
a := func() { fmt.Printf("i, j: %d, %dn", i, j) }
至於為何要用匿名函數如此的轉一圈,是因為要參照閉包的概念,此概念省略不表,多寫點程式碼試試就能體會了。
package main type Integer int64 func main() { var srcInt Integer srcInt = int64(1000) }
結果:
方法能給使用者定義的型別新增新的行為。方法實際上也是函數,只是在宣告時,在關鍵字func 和方法名之間增加了一個引數
例如:
這是函數,它的呼叫就是直接在使用的時候 傳入引數獲取返回值就行
func getStudentName(student Student)(name string) { //返回值 return student.Name }
這是方法
package main import ( "fmt" ) type Student struct { Name string Age int } //Student類的方法 使用值接收者實現了一個方法 func (student Student) getStudentName()(string){ return student.Name } //Student類的方法 使用指標接收者實現了一個方法 func (student *Student) changeStudentName(name string){ student.Name = name fmt.Println("方法執行之後name",student.Name) } //Student類的方法 使用指標接收者實現了一個方法 func (student Student) changeStudentNameByValue(name string){ student.Name = name fmt.Println("方法執行之後name",student.Name) } func main() { bigOrange:=Student{ Name:"BigOrange",Age:18, } bigApple:=Student{ Name:"BigApple",Age:20, } //使用函數獲取學生名稱 name1 := getStudentName(bigOrange) name2 := getStudentName(bigApple) fmt.Println("========通過傳地址ChangeName之後==========") fmt.Println("方法執行之前name",name1) bigOrange.changeStudentName("BigBanana") name1 = bigOrange.getStudentName() fmt.Println("方法返回之後Name",name1) fmt.Println("========通過傳值ChangeName之後===========") fmt.Println("方法執行之前name",name2) bigApple.changeStudentNameByValue("BigPear") name2 = bigApple.getStudentName() fmt.Println("方法返回之後Name",name2) }
結果:
========通過傳地址ChangeName之後==========
方法執行之前name BigOrange
方法執行之後name BigBanana
方法返回之後Name BigBanana
========通過傳值ChangeName之後===========
方法執行之前name BigApple
方法執行之後name BigPear
方法返回之後Name BigApple
上面的例子中
分別使用了函數和方法進行獲取學生姓名
分別使用了傳值和傳地址的方式對學生名稱進行修正
方法如果使用 值接收者,那麼呼叫者可以是值接收者型別、也可以是它的指標型別,請看下面的例子(補充上例):
fmt.Println("========使用指標來呼叫值型別宣告的接收者方法===========") bigGrape := &Student{ Name:"bigGrape",Age:22} //取地址!!!! name3 := bigGrape.getStudentName(); fmt.Println("========通過傳值ChangeName之後===========") fmt.Println("方法執行之前name",name3) bigGrape.changeStudentNameByValue("BigXXXX") name3 = bigGrape.getStudentName() fmt.Println("方法返回之後Name",name3)
結果:
========使用指標來呼叫值型別宣告的接收者方法===========
name bigGrape
========通過傳值ChangeName之後===========
方法執行之前name bigGrape
方法執行之後name BigXXXX
方法返回之後Name bigGrape
如上程式碼 使用了&獲取地址,所以bigGrape是一個student型別的指標。下面的程式碼和上例一樣,直接使用了【變數.方法】的方式呼叫方法,結果也和值型別呼叫的一樣。
為什麼?
【Go 在程式碼背後的執行動作】
name4:=(*bigGrape).getStudentName()
Go 編譯器為了支援這種方法呼叫背後做的事情。【指標被解除參照為值】,這樣就符合了值接收者的要求。再強調一次,getStudentName 操作的是一個副本,只不過這次操作的是從bigGrape指標指向的值的副本。
同理還記得上面的,這句程式碼嗎?對bigOrange這個變數修改了名稱
bigOrange.changeStudentName("BigBanana")
bigOrange和bigApple明顯是值型別,但是 changeStudentName 接收者是一個指標型別,為什麼能呼叫,也是基於Go程式碼背後的執行動作,將值型別取了地址。
(&bigOrange).changeStudentName("BigOrange")
所以對於Go語言呼叫方法的型別,使用值或者指標都是可以的,不用拘泥於型別。
到此這篇關於Go語言函數的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45