參考連接 http://www.javashuo.com/article/p-uqzutwwu-bp.htmlgolang
type是golang中很是重要的關鍵字,常見的就是定義結構體,可是其功能遠不止是像c中那樣只定義結構體,在golang中type關鍵字的功能能夠說是很是豐富,經過參考相關的文章和源碼,總結以下:數組
type person struct { name string //注意後面不能有逗號 age int }
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()) //調用對象的方法 }
//結構體內嵌匿名成員定義 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) }
這也是最經常使用的一種,例子以下,很少贅述指針
//接口定義 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) }
//如下是定義一個函數類型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