Go從入門到精通——函式——可變引數——引數數量不固定的函式形式
阿新 • • 發佈:2022-05-28
可變引數——引數數量不固定的函式形式
Go 語言支援可變引數特性,函式宣告和呼叫時沒有固定數量的引數,同時也提供了一套方法進行可變引數的多級傳遞。
Go 語言的可變引數格式如下:
func 函式名(固定引數列表, v...T)(返回引數列表){
函式體
}
特性如下:
- 可變引數一般被放置在函式列表的末尾,前面是固定引數列表,當沒有固定引數時,所有變數就將是可變引數。
- v為可變引數變數,型別為 []T,也就是擁有多個 T 元素的 T 型別的切片, v 和 T 之間由 "..." 即 3 個點組成。
- T 為可變引數的型別,當 T 為 interface{}時,傳入的可以是任意型別。
一、fmt 包中的例子
可變引數有兩種形式:所有引數都是可變引數的形式,如 fmt.Println,以及部分是可變引數的形式,如 fmt.Printf,可變引數只能出現在引數的後半部分,因此不可變的引數只能放在引數的前半部分。
1、所有引數都是可變引數:fmt.Println (go version go1.18.1 windows/amd64)
// Println formats using the default formats for its operands and writes to standard output. // Spaces are always added between operands and a newline is appended. // It returns the number of bytes written and any write error encountered. func Println(a ...any) (n int, err error) { return Fprintln(os.Stdout, a...) }
fmt.Println 在使用時,傳入的值型別不受限制,例如:
fmt.Println(5,"Hello", &struct{a int}{1},true)
2. 部分引數是可變引數:fmt.Printf (go version go1.18.1 windows/amd64)
fmt.Printf 的第一個引數為引數列表,後面的引數是可變引數,fmt.Printf 函式的格式如下:
// Printf formats according to a format specifier and writes to standard output. // It returns the number of bytes written and any write error encountered. func Printf(format string, a ...any) (n int, err error) { return Fprintf(os.Stdout, format, a...) }
fmt.Printf()函式在呼叫時,第一個函式始終必須傳入字串,對應引數是 format,後面的引數變數可以變化,使用時候,程式碼如下:
fmt.Printf("pure string\n")
fmt.Printf("value: %v %f\n", true, math.Pi)
二、遍歷可變引數列表——獲取每一個引數的值
可變引數列表的數量不固定,傳入的引數是一個切片。如果需要獲得每一個引數的具體值時,可以對可變引數變數進行遍歷。
package main
import (
"bytes"
"fmt"
)
//定義一個函式,引數數量為 0~n,型別約束為字串
func joinStrings(slist ...string) string {
//定義一個位元組緩衝,快速地連線字串
var b bytes.Buffer
//遍歷可變引數列表 slist,型別為 []string
for _, s := range slist {
//將遍歷出的字串連續寫入位元組陣列
b.WriteString(s)
}
//將連線好的位元組陣列轉換為字串輸出
return b.String()
}
func main() {
//輸入3個字串,將他們形成一個字串
fmt.Println(joinStrings("ping", "and", "rat"))
fmt.Println(joinStrings("我", "愛", "中國"))
}
三、獲得可變引數型別——獲得每一個引數的型別
當可變引數為 interface{}型別時,可以傳入任何型別的值。此時,如果需要獲得變數的型別,可以通過 switch 型別分支獲得變數的型別。
下面演示將一系列不同型別的值傳入 printTypeValue()函式,該函式將分別為不同的引數列印它們的值和型別的詳細描述。
package main
import (
"bytes"
"fmt"
)
func printTypeValue(slist ...interface{}) string {
//位元組緩衝作為快速字串連線
var b bytes.Buffer
//遍歷引數
for _, s := range slist {
//將 interace{} 型別格式化為字串
str := fmt.Sprintf("%v", s)
//型別的字串描述
var typeString string
//對 s 進行型別斷言
switch s.(type) {
case bool:
typeString = "bool"
case string:
typeString = "string"
case int:
typeString = "int"
}
//寫值字串字首
b.WriteString("value: ")
//寫入值
b.WriteString(str)
//寫型別字首
b.WriteString(" type: ")
//寫型別字串
b.WriteString(typeString)
//寫入換行符
b.WriteString("\n")
}
return b.String()
}
func main() {
//將不同型別的變數通過 printTypeValue() 打印出來
fmt.Println(printTypeValue(100, "str", true))
}
程式碼執行結果:
Starting: D:\go-testfiles\bin\dlv.exe dap --check-go-version=false --listen=127.0.0.1:52207 from d:\go-testfiles
DAP server listening at: 127.0.0.1:52207
Type 'dlv help' for list of commands.
value: 100 type: int
value: str type: string
value: true type: bool
Process 9212 has exited with status 0
Detaching
dlv dap (12820) exited with code: 0
四、在多個可變引數函式中傳遞引數
可變引數變數是一個包含所有引數的切片,如果要在多個可變引數中傳遞引數,可以在傳遞時在可變引數變數中預設新增 "...",將切片中的元素進行傳遞,而不是傳遞可變引數變數本身。
package main
import "fmt"
func rawPrint(rawList ...interface{}) {
//遍歷可變引數切片
for _, a := range rawList {
//列印引數
fmt.Println(a)
}
}
//列印函式封裝
func print(slist ...interface{}) {
//將slist可變引數切片完整傳遞給下一個函式
rawPrint(slist...)
}
func main() {
print(1, 2, 3)
}