golang:函數總結


golang保留的函數

init(), main()是golang的保留函數,有如下特點:

  • main() 只能用在main包中,僅可定義一個,init() 可定義任意包,可重復定義,建議只定義一個
  • 兩個函數定義時不能有任何返回值
  • 只能由go自動調用,不可被引用
  • init() 先於 main() 執行,並不能被其他函數調用,執行時按照main import順序執行。

包的執行順序

  • Go的初始化和執行總是從main.main函數(main包導入其它的包)
  • 同包下的不同 .go 文件,按照以文件名或包路徑名的字符串順序“從小到大”排序順序執行
  • 其他的包只有被main包 import 才會執行,按照 import 的先后順序執行;
  • 如果某個包被多次導入的話,在執行的時候只會導入一次;
  • 當一個包被導入時,如果它還導入了其它的包,則先將其它的包包含進來;
  • 導入順序與初始化順序相反 main => p1 => p2 | p2 => p1 => p
  • main被最后一個初始化,因其總是依賴其他包

函數

函數是將具有獨立功能的代碼組織成為一個整體,使其具有特殊功能的代碼集。在Go語言中,函數是一種數據類型,其特性有如下:

  • 支持匿名函數
  • 支持帶有變量名的返回值
  • 支持多值返回
  • 支持匿名函數
  • 不支持重載,一個包中不能有兩個名字一樣的函數。

定義語法


func test(){

}

func test(a int, b int){

}

func test(a,b int){

}

func test(a,b int list...int){

}

func test(a int, b int) int{

}

func test(a int, b int ) (int,int){

}

func test(a,b int) (num int, err error){

}

花括號必須與函數聲明在同一行,這種寫法是錯誤的

func test()
{

}

命名返回值名稱

package main

import "fmt"

func test(a, b, c int) (he int, cha int) {
	he = a + b + c
	cha = a - b - c
	return
}

func main() {

	a, b := test(15, 10, 5)
	fmt.Println(a)
	fmt.Println(b)

}

_標識符,用來忽略返回值

函數參數傳遞方式

\1. 值傳遞
\2. 引用傳遞

注意:無論是值傳遞,還是引用傳遞,傳遞給函數的都是變量的副本,不過,值傳遞是值的持貝。引用傳遞是地址的持貝,一般來說,地址持貝更為高效。而值持貝取決於拷貝的對象大小,對象越大,則性能越低。

注意2:map、slice、chan、指針、interface默認以引用的方式傳遞

自定義函數類型

package main

import "fmt"

type ty_func func(int, int) int

func add(a, b int) int {
	return a + b
}

func operator(op ty_func, a, b int) int {
	return op(a, b)
}

func main() {
	c := add
	sum := operator(c, 100, 200)

	fmt.Println(sum)
}

不定參數

  • 不定參數可以通過下標/循環方式獲取參數值
  • 不定參數在定義時,固定參數放前面,不定參數放后面
  • 在對函數調用時,固定參數必須傳值,不定參數可以根據需要來決定是否要傳值

語法

func {func_name}({param} ...{type}){
	func_body
}

參數的類型是一個 {type} 類型的集合

練習:寫一個函數add,支持1個或多個int相加,並返回相加結果

package main

import "fmt"

func test(num ...int) {
	var sum int
	for n := 1; n <= len(num); n++ {
		sum += num[(n - 1)]
	}
	fmt.Println(sum)
}

func main() {
	test(1)
	test(1, 2, 3)
    test(1, 2, 3, 4)
}

練習:寫一個函數concat,支持1個或多個string相拼接,並返回結果

func concat(age ...string) {
	var str string
	for _,v := range age {
		str += v
	}

	fmt.Println(str)
}

func main() {
	concat("hellow", " world", " go")

}

延遲調用defer

  • 當函數返回時,執行defer語句。因此,可以用來做資源清理
  • 多個defer語句,按LIFO(后進先出)的順序執行
  • defer語句中的變量,在defer聲明時就決定了。

用途

  • 關閉文件句柄
  • 鎖資源釋放
  • 數據庫連接釋放

defer語句中的變量,在defer聲明時就決定了其值

func defer_test() {
	i := 0
	defer fmt.Println(i)

	i = 10

	fmt.Println(i)
}

func main() {
	defer_test()
}

多個defer按LIFO(后進先出)的順序執行

func defer_test() {
	i := 0
	defer fmt.Println(i)

	i = 10

	fmt.Println(i)
}

func main() {
	defer_test()
}

defer的作用域,此處可以看到,defer的傳入不是在main的作用域下,測試可發現 defer只會在當前函數和方法返回之前被調用。

package main

import "fmt"

func main() {
   fmt.Println("block starts")
   {
      defer fmt.Println("defer runs")
      fmt.Println("block ends")
   }

   fmt.Println("main ends")
}

函數作用域

全局變量:既能在函數中使用,也能在其他函數中使用,可以稱為定義在函數外的變量。

局部變量:定義在函數內部的變量成為局部變量,局部變量的作用域在函數內部。

如果全局變量的名字和局部變量的名字相同,使用的是局部變量

匿名函數

package main

import "fmt"

var (
	test = func(a, b int) int {
		return a + b
	}(10, 20)
)

var test1 = func(age ...int) int {
	var sum int

	for n := 0; n < len(age); n++ {
		sum += age[n]
	}
	return sum
}

func main() {
	c := test
	fmt.Println(c)

	d := test1(100, 100, 100)
	fmt.Println(d)
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM