您好,登錄后才能下訂單哦!
對于GoLang函數的定義或者說理解:
函數是結構化編程中最小的模塊單元,日常開發過程中,將復雜的算法過程分解為若干個小任務(代碼塊),使程序的結構性更清晰,程序可讀性提升,易于后期維護和讓別人讀懂你的代碼。
另外為了更好的重用你的代碼,可以把重復性的任務抽象成一個函數。
Go語言中使用關鍵詞func來定義一個函數,并且左花括號不能另起一行,比如:
func hello(){ //左花括號不能另起一行 println("hello") }
Go語言中定義和應用函數時,有如下需要注意的點:
函數無須前置聲明
不支持命名嵌套定義,支持匿名嵌套
函數只能判斷是否為nil,不支持其它比較操作
支持多返回值
支持命名返回值
支持返回局部變量指針
支持匿名函數和閉包
func hello() { //左括號不能另起一行 } func add(x,y int) (sum int){ //命名返回值 sum = x + y return } func vals()(int,int){ //支持多返回值 return 2,3 } func a(){} func b(){} func add(x,y int) (*int){ //支持返回局部變量指針 sum := x + y return &sum } func main(){ println(a==b) //只能判斷是否為nil,不支持其它比較操作 func hello() { //不支持命名嵌套定義 println("hello") } }
具備相同簽名(參數和返回值)的函數才視為同一類型函數,比如:
func hello() { fmt.Println("hello") } func say(f func()){ f() } func main(){ f := hello say(f) }
參數:
Go語言中給函數傳參時需要注意以下幾點:
不支持默認參數
不支持命名實參
參數視作為函數的局部變量
必須按簽名順序傳遞指定類型和數量的實參
相鄰的同類型參數可以合并
支持不定長變參,實質上是slice
func test(x,y int, s string, _ bool){ //相鄰的同類型參數可以合并 return } func add(x ,y int) int { //參數視作為函數的局部變量 x := 100 //no new variables on left side of := var y int = 200 //y redeclared in this block return x +y } func sum(nums ...int) { //變參函數 total := 0 for _, num := range nums { total += num } fmt.Println(total) } func main(){ //test(1,2,"s") //not enough arguments in call to test test(1,2,"s",false) nums := []int{1, 2, 3} sum(nums...) }
不管傳遞的是指針、引用還是其它類型參數,都是值拷貝傳遞的,區別在于拷貝的目標是目標對象還是拷貝指針而已。
在函數調用之前,編譯器會為形參和返回值分配內存空間,并將實參拷貝到形參內存。比如:
func test1(x *int){ fmt.Printf("%p, %v\n",&x ,x) } func main(){ a := 0x100 p := &a fmt.Printf("%p, %v\n", &p, p) test1(p) } 輸出: 0xc42002c020, 0xc42000a320 0xc42002c030, 0xc42000a320 從結構中看出, 實參和形參指向同一目標,但是傳遞的指針是被賦值了的
如果函數參數和返回值過多,可以將其封裝成一個結構體類型,比如:
type serverOption struct{ addr string port int path string timeout time.Duration } func newOption() * serverOption{ return &serverOption{ addr:"127.0.0.1", port:8080, path:"/var/www", timeout: time.Second * 5, } } func (s *serverOption)server(){ println("run server") } func main(){ s := newOption() s.port = 80 s.server() for{} }
變參:
變參本質上是一個切片(slice),只能接收一到多個同類型參數,且必須放在參數列表尾部,比如:
func add(args ...int) int { total := 0 for _, v := range args { total += v } return total } func main() { fmt.Println(add(1,2,3)) }
變參既然是切片,那是否可以直接傳個切片或數組呢?
func test1(s string, a ...int){ fmt.Printf("%T, %v\n", a, a) //[]int, [1 2 3 4] } { a := [4]int{1,2,3,4} test1("s", a) //cannot use a (type [4]int) as type int in argument to test1 test1("s", a[:] //cannot use a[:] (type []int) as type int in argument to test1 test1("s", a[:]...) //切片展開 }
變參既然是切片,那么參數復制的是切片的本身,并不包括底層的數組,因此可以修改原數據,但是可以copy底層數據,防止原數據被修改,比如:
func test1(a ...int){ for i := range a{ a[i] += 100 } } func main(){ a := [4]int{1,2,3,4} // b := make([]int,0) // copy(b,a[:]) // test1(b[:]...) test1(a[:]...) for i := range a{ fmt.Println(a[i]) } }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。