日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)GO教程:Go語言可變參數(shù)(變參函數(shù))

在C語言時代大家一般都用過 printf() 函數(shù),從那個時候開始其實已經(jīng)在感受可變參數(shù)的魅力和價值,如同C語言中的 printf() 函數(shù),Go語言標(biāo)準(zhǔn)庫中的 fmt.Println() 等函數(shù)的實現(xiàn)也依賴于語言的可變參數(shù)功能。

本節(jié)我們將介紹可變參數(shù)的用法。合適地使用可變參數(shù),可以讓代碼簡單易用,尤其是輸入輸出類函數(shù),比如日志函數(shù)等。

可變參數(shù)類型

可變參數(shù)是指函數(shù)傳入的參數(shù)個數(shù)是可變的,為了做到這點,首先需要將函數(shù)定義為可以接受可變參數(shù)的類型:

func myfunc(args ...int) {
    for _, arg := range args {
        fmt.Println(arg)
    }
}

上面這段代碼的意思是,函數(shù) myfunc() 接受不定數(shù)量的參數(shù),這些參數(shù)的類型全部是 int,所以它可以用如下方式調(diào)用:

myfunc(2, 3, 4)
myfunc(1, 3, 7, 13)

形如
...type格式的類型只能作為函數(shù)的參數(shù)類型存在,并且必須是最后一個參數(shù),它是一個語法糖(syntactic sugar),即這種語法對語言的功能并沒有影響,但是更方便程序員使用,通常來說,使用語法糖能夠增加程序的可讀性,從而減少程序出錯的可能。

從內(nèi)部實現(xiàn)機理上來說,類型
...type本質(zhì)上是一個數(shù)組切片,也就是
[]type,這也是為什么上面的參數(shù) args 可以用 for 循環(huán)來獲得每個傳入的參數(shù)。

假如沒有
...type這樣的語法糖,開發(fā)者將不得不這么寫:

func myfunc2(args []int) {
    for _, arg := range args {
        fmt.Println(arg)
    }
}

從函數(shù)的實現(xiàn)角度來看,這沒有任何影響,該怎么寫就怎么寫,但從調(diào)用方來說,情形則完全不同:

myfunc2([]int{1, 3, 7, 13})

大家會發(fā)現(xiàn),我們不得不加上
[]int{}來構(gòu)造一個數(shù)組切片實例,但是有了
...type這個語法糖,我們就不用自己來處理了。

任意類型的可變參數(shù)

之前的例子中將可變參數(shù)類型約束為 int,如果你希望傳任意類型,可以指定類型為 interface{},下面是Go語言標(biāo)準(zhǔn)庫中 fmt.Printf() 的函數(shù)原型:

func Printf(format string, args ...interface{}) {
    // ...
}

用 interface{} 傳遞任意類型數(shù)據(jù)是Go語言的慣例用法,使用 interface{} 仍然是類型安全的,這和 C/ C++ 不太一樣,下面通過示例來了解一下如何分配傳入 interface{} 類型的數(shù)據(jù)。

package main
import "fmt"
func MyPrintf(args ...interface{}) {
    for _, arg := range args {
        switch arg.(type) {
            case int:
                fmt.Println(arg, "is an int value.")
            case string:
                fmt.Println(arg, "is a string value.")
            case int64:
                fmt.Println(arg, "is an int64 value.")
            default:
                fmt.Println(arg, "is an unknown type.")
        }
    }
}
func main() {
    var v1 int = 1
    var v2 int64 = 234
    var v3 string = "hello"
    var v4 float32 = 1.234
    MyPrintf(v1, v2, v3, v4)
}

該程序的輸出結(jié)果為:

1 is an int value.
234 is an int64 value.
hello is a string value.
1.234 is an unknown type.

遍歷可變參數(shù)列表——獲取每一個參數(shù)的值

可變參數(shù)列表的數(shù)量不固定,傳入的參數(shù)是一個切片,如果需要獲得每一個參數(shù)的具體值時,可以對可變參數(shù)變量進行遍歷,參見下面代碼:

package main

import (
    "bytes"
    "fmt"
)
// 定義一個函數(shù), 參數(shù)數(shù)量為0~n, 類型約束為字符串
func joinStrings(slist ...string) string {

    // 定義一個字節(jié)緩沖, 快速地連接字符串
    var b bytes.Buffer
    // 遍歷可變參數(shù)列表slist, 類型為[]string
    for _, s := range slist {
        // 將遍歷出的字符串連續(xù)寫入字節(jié)數(shù)組
        b.WriteString(s)
    }

    // 將連接好的字節(jié)數(shù)組轉(zhuǎn)換為字符串并輸出
    return b.String()
}

func main() {
    // 輸入3個字符串, 將它們連成一個字符串
    fmt.Println(joinStrings("pig ", "and", " rat"))
    fmt.Println(joinStrings("hammer", " mom", " and", " hawk"))
}

代碼輸出如下:

pig and rat
hammer mom and hawk

代碼說明如下:

  • 第 8 行,定義了一個可變參數(shù)的函數(shù),slist 的類型為 []string,每一個參數(shù)的類型都是 string,也就是說,該函數(shù)只接受字符串類型作為參數(shù)。
  • 第 11 行,bytes.Buffer 在這個例子中的作用類似于 StringBuilder,可以高效地進行字符串連接操作。
  • 第 13 行,遍歷 slist 可變參數(shù),s 為每個參數(shù)的值,類型為 string。
  • 第 15 行,將每一個傳入?yún)?shù)放到 bytes.Buffer 中。
  • 第 19 行,將 bytes.Buffer 中的數(shù)據(jù)轉(zhuǎn)換為字符串作為函數(shù)返回值返回。
  • 第 24 行,輸入 3 個字符串,使用 joinStrings() 函數(shù)將參數(shù)連接為字符串輸出。
  • 第 25 行,輸入 4 個字符串,連接后輸出。

如果要獲取可變參數(shù)的數(shù)量,可以使用 len() 函數(shù)對可變參數(shù)變量對應(yīng)的切片進行求長度操作,以獲得可變參數(shù)數(shù)量。

獲得可變參數(shù)類型——獲得每一個參數(shù)的類型

當(dāng)可變參數(shù)為 interface{} 類型時,可以傳入任何類型的值,此時,如果需要獲得變量的類型,可以通過 switch 獲得變量的類型,下面的代碼演示將一系列不同類型的值傳入 printTypeValue() 函數(shù),該函數(shù)將分別為不同的參數(shù)打印它們的值和類型的詳細描述。

打印類型及值:

package main

import (
    "bytes"
    "fmt"
)

func printTypeValue(slist ...interface{}) string {

    // 字節(jié)緩沖作為快速字符串連接
    var b bytes.Buffer

    // 遍歷參數(shù)
    for _, s := range slist {

        // 將interface{}類型格式化為字符串
        str := fmt.Sprintf("%v", s)

        // 類型的字符串描述
        var typeString string

        // 對s進行類型斷言
        switch s.(type) {
        case bool:    // 當(dāng)s為布爾類型時
            typeString = "bool"
        case string:    // 當(dāng)s為字符串類型時
            typeString = "string"
        case int:    // 當(dāng)s為整型類型時
            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))
}

代碼輸出如下:

value: 100 type: int
value: str type: string
value: true type: bool

代碼說明如下:

  • 第 8 行,printTypeValue() 輸入不同類型的值并輸出類型和值描述。
  • 第 11 行,bytes.Buffer 字節(jié)緩沖作為快速字符串連接。
  • 第 14 行,遍歷 slist 的每一個元素,類型為 interface{}。
  • 第 17 行,使用 fmt.Sprintf 配合%v動詞,可以將 interface{} 格式的任意值轉(zhuǎn)為字符串。
  • 第 20 行,聲明一個字符串,作為變量的類型名。
  • 第 23 行,switch s.(type) 可以對 interface{} 類型進行類型斷言,也就是判斷變量的實際類型。
  • 第 24~29 行為 s 變量可能的類型,將每種類型的對應(yīng)類型字符串賦值到 typeString 中。
  • 第 33~42 行為寫輸出格式的過程。

在多個可變參數(shù)函數(shù)中傳遞參數(shù)

可變參數(shù)變量是一個包含所有參數(shù)的切片,如果要將這個含有可變參數(shù)的變量傳遞給下一個可變參數(shù)函數(shù),可以在傳遞時給可變參數(shù)變量后面添加
...,這樣就可以將切片中的元素進行傳遞,而不是傳遞可變參數(shù)變量本身。

下面的例子模擬 print() 函數(shù)及實際調(diào)用的 rawPrint() 函數(shù),兩個函數(shù)都擁有可變參數(shù),需要將參數(shù)從 print 傳遞到 rawPrint 中。

可變參數(shù)傳遞:

package main

import "fmt"

// 實際打印的函數(shù)
func rawPrint(rawList ...interface{}) {

    // 遍歷可變參數(shù)切片
    for _, a := range rawList {

        // 打印參數(shù)
        fmt.Println(a)
    }
}

// 打印函數(shù)封裝
func print(slist ...interface{}) {

    // 將slist可變參數(shù)切片完整傳遞給下一個函數(shù)
    rawPrint(slist...)
}

func main() {

    print(1, 2, 3)
}

代碼輸出如下:

1
2
3

對代碼的說明:

  • 第 9~13 行,遍歷 rawPrint() 的參數(shù)列表 rawList 并打印。
  • 第 20 行,將變量在 print 的可變參數(shù)列表中添加...后傳遞給 rawPrint()。
  • 第 25 行,傳入 1、2、3 這 3 個整型值并進行打印。

如果嘗試將第 20 行修改為:

rawPrint("fmt", slist)

再次執(zhí)行代碼,將輸出:

[1 2 3]

此時,slist(類型為 []interface{})將被作為一個整體傳入 rawPrint(),rawPrint() 函數(shù)中遍歷的變量也就是 slist 的切片值。

可變參數(shù)使用
...進行傳遞與切片間使用 append 連接是同一個特性。


本文名稱:創(chuàng)新互聯(lián)GO教程:Go語言可變參數(shù)(變參函數(shù))
標(biāo)題來源:http://m.5511xx.com/article/cohcpsj.html