再golang中,我們要充分理解interface和struct這兩種數據類型。為此,我們需要優先理解type的作用。
type是golang語言中定義數據類型的唯一關鍵字。對於type中的匿名成員和指針成員,這里先不講,重點講解interface和struct這兩種特殊的數據類型。
interface和struct也是數據類型,特殊在於interface作為萬能的接口類型,而struct作為常用的自定義數據類型的關鍵字。說到這里相比大家已經明白interface的側重點在於接口的定義(方法),而struct側重點在於數據結構的定義。使用struct定義了數據結構,可以直接使用func方法定義數據結構中使用的方法。但是為了解耦,為了擴展,一般在真正設置功能性函數時,除了內置的數據類型外,都推薦使用接口的方法來傳遞相關方法。
既然推薦使用接口的方法來作為參數,那么具體結構中的數據成員又如何訪問呢?golang提供了非常方便的類型查詢和類型轉換方法。名稱.(type)用於類型查詢,名稱.(具體類型)用於類型轉換。因此,使用接口作為函數參數是很有價值的。
另外,我們還需要明白對象和對象指針在golang中的微妙處理,golang可以自動將對數據類型定義的方法抓轉換成對數據類型指針定義的方法。但不能自動的將對數據類型指針的方法轉換為對數據類型定義的方法。
以下是我們的測試程序,注釋已經注明了相關說明。
package main import "fmt" //定義一個接口 type Stryc interface { Int() int } //定義一個自定義數據類型 type myCls struct { value int } //使用數據類型指針綁定方法(在調用方法時,數據類型在golang中會默認轉換為數據類型指針進行使用) func(a * myCls) Int() int{ return a.value } //定義一個函數,參數為一個自定義的數據類型 func printTheValueByStruct(arg myCls){ fmt.Printf("the value is %d \n",arg.Int()) } //定義一個函數,參數為一個接口 func printTheValue(arg Stryc) int{ fmt.Printf("the value is %d \n",arg.Int()/*使用接口調用接口的方法*/) return arg.Int() } //定義一個函數,參數為動態個數的接口類型參數 func printAnyValue(args ...interface{}){ //使用for range方法獲取每一個接口 for _,arg := range args{ //使用.(type)方法查詢接口的數據類型 switch arg.(type) { case int: fmt.Println("the type is int") case string: fmt.Println("the type is string") case myCls:/*是自定義數據類型*/ //使用.(數據類型)進行強轉 var b myCls = arg.(myCls) fmt.Println("the type is myCls, the function value is ", b.Int()/*d調用數據類型的方法,golang會轉換為數據指針類型調用*/,"the struct value is ", b.value/*調用數據結構的數據*/) case Stryc:/*是定義的接口數據類型*/ fmt.Println("the type is Stryc interface, the function value is ", arg.(Stryc).Int()/*將接口強轉到指定接口,並調用方法*/) } } } func main(){ var V1 *myCls = new(myCls) //創建一個對象指針 V1.value = 1111111 //給對象賦值 var V2 myCls = myCls{222222222} //創建一個對象,給對象賦值 var a interface {}=myCls{33333} //創建一個對象,將對象賦值后傳給一個萬能類型接口 var a1 interface{}=&myCls{444444}//創建一個對象,將對象指針傳給一個萬能類型接口 fmt.Println("hello world!") printTheValue(V1) //V1會轉換為Stryc接口被調用其中的方法 printTheValue(a1.(Stryc)) //萬能接口a1中放置的對象指針被強制轉為Stryc接口調用 printTheValueByStruct(*V1) //強制將V1的對象使用*顯示傳入函數,因為參數是對象 printTheValueByStruct(a.(myCls))//強制將萬能接口a中放置的對象轉換為對象傳入函數,因為參數是對象 printTheValue(&V2) //將對象的指針傳入函數,golang將其轉換為Stryc接口 printAnyValue(V1/*傳入一個指針,會同Stryc接口數據類型匹配*/, V2/*傳入一個對象,會同myCls數據類型匹配*/, *V1/*將指針顯示為對象傳入,會同myCls數據類型匹配*/, &V2/*將對象的指針傳入,會同Stryc接口數據類型匹配*/) }
以下是執行結果
hello world! the value is 1111111 the value is 444444 the value is 1111111 the value is 33333 the value is 222222222 the type is Stryc interface, the function value is 1111111 the type is myCls, the function value is 222222222 the struct value is 222222222 the type is myCls, the function value is 1111111 the struct value is 1111111 the type is Stryc interface, the function value is 222222222