golang type

參考連接 http://www.javashuo.com/article/p-uqzutwwu-bp.htmlgolang

type是golang中很是重要的關鍵字,常見的就是定義結構體,可是其功能遠不止是像c中那樣只定義結構體,在golang中type關鍵字的功能能夠說是很是豐富,經過參考相關的文章和源碼,總結以下:數組

1 定義結構體

type person struct {
    name string  //注意後面不能有逗號
    age  int
}

2 類型定義,至關於定義一個別名

type name string   //name類型與string等價
例子:
type name string

func main() {
    var myname name = "taozs" //其實就是字符串類型
    l := []byte(myname)       //字符串轉字節數組
    fmt.Println(len(l))       //字節長度
}

ps:定義的新類型(別名),能夠用來定義方法,好比,我設置string的別名爲name,能夠用name定義方法,以下:函數

type name string

func (n name) len() int {
    return len(n)
}

func main() {
    var myname name = "taozs" //其實就是字符串類型
    l := []byte(myname)       //字符串轉字節數組
    fmt.Println(len(l))       //字節長度
    fmt.Println(myname.len()) //調用對象的方法
}

3 type定義結構體時,能夠內嵌匿名成員

//結構體內嵌匿名成員定義

type person struct {
string  //直接寫類型,匿名
age int
}

func main() {
    //結構體匿名成員初始化
    p := person{string: "taozs", age: 18}//能夠省略部分字段,如:person{string: "taozs"}。也能夠這樣省略字段名:person{「taozs」, 18},但必須寫全了,不能夠省略部分字段
    //結構體匿名成員訪問
    fmt.Println(p.string) //注意不能用強制類型轉換(類型斷言):p.(string)
}

當結構體只有惟一一個匿名成員的case時.net

//結構體內嵌匿名成員定義
type person struct {
    string
}

func main() {
    //結構體匿名成員初始化
    p := person{string: "taozs"} //也可這樣:person{"taozs"}
    //結構體匿名成員訪問
    fmt.Println(p.string) //注意不能用強制類型轉換(類型斷言):p.(string)
}

4 定義接口類型

這也是最經常使用的一種,例子以下,很少贅述指針

//接口定義
type Personer interface {
    Run()
    Name() string
}
//實現接口,注意實現接口的不必定只是結構體,也能夠是函數對象,參見下面第5條
type person struct {
    name string
    age  int
}

func (person) Run() {
    fmt.Println("running...")
}

//接收參數person不能夠是指針類型,不然不認爲是實現了接口

func (p person) Name() string {
    return p.name
}

func main() {
    //接口類型的變量定義
    var p Personer
    fmt.Println(p) //值<nil>
    //實例化結構體,並賦值給interface
    p = person{"taozs", 18} //或者:&person{"taozs", 18}
    p.Run()
    fmt.Println(p.Name())
    var p2 person = p.(person) //類型斷言,接口類型斷言到具體類型
    fmt.Println(p2.age)
}

ps:當一個結構體實現了某個接口的全部方法時,才能算是實現了這個接口對象

//另外,類型斷言返回值也能夠有第二個bool值,表示斷言是否成功,以下:
if p2, ok := p.(person); ok {//斷言成功ok值爲true
    fmt.Println(ok)
    fmt.Println(p2.age)
}

5 定義函數類型

//如下是定義一個函數類型handler
type handler func(name string) int

//針對這個函數類型能夠再定義方法,如:
func (h handler) add(name string) int {
    return h(name) + 10
}

 

下面是一個比較全面的例子:blog

package main

import (
    "fmt"
)

//定義接口
type adder interface {
    add(string) int
}

//定義函數類型
type handler func(name string) int

//實現函數類型方法
func (h handler) add(name string) int {
    return h(name) + 10
}

//函數參數類型接受實現了adder接口的對象(函數或結構體)
func process(a adder) {
    fmt.Println("process:", a.add("taozs"))
}

//另外一個函數定義
func doubler(name string) int {
    return len(name) * 2
}

//非函數類型
type myint int

//實現了adder接口
func (i myint) add(name string) int {
    return len(name) + int(i)
}

func main() {
    //注意要成爲函數對象必須顯式定義handler類型
    var my handler = func(name string) int {
        return len(name)
    }

    //如下是函數或函數方法的調用
    fmt.Println(my("taozs"))                   //調用函數
    fmt.Println(my.add("taozs"))               //調用函數對象的方法
    fmt.Println(handler(doubler).add("taozs")) //doubler函數顯式轉換成handler函數對象而後調用對象的add方法
    //如下是針對接口adder的調用
    process(my)               //process函數須要adder接口類型參數
    process(handler(doubler)) //由於process接受的參數類型是handler,因此這兒要強制轉換
    process(myint(8))         //實現adder接口不只能夠是函數也能夠是結構體

}

 難點:fmt.Println(handler(doubler).add("taozs")) //doubler函數顯式轉換成handler函數對象而後調用對象的add方法接口

  這波操做比較懵逼,首先說下這波操做一會兒就能看懂的,看註釋,很明顯,強制類型轉換,doubler函數強制轉換成了handler這種類型,這個操做最後的輸出是20,怎麼得來的呢?看add方法的實現:字符串

func (h handler) add(name string) int {
	return h(name) + 10
}

   能夠看到,像是聲明某個結構體的方法的方式,這裏規定了add屬於handler這個函數類型,能夠看到add函數體中有一個h(name),是否是看的有點莫名其妙?其實就像是接口同樣,哪一個句柄調用了add方法,就執行哪一個句柄。能夠看到get

  fmt.Println(handler(doubler).add("taozs"))

  是doubler調用了add,那麼這個h(name)就等價於doubler(name),由於這裏name="taozs",那麼先執行add函數,執行到return這句的時候,執行h(name)即doubler(name),執行結果是len(name)*2 = 10。因而,結果就是20

相關文章
相關標籤/搜索