Golang通脈之類型定義

1、自定義類型

在Go語言中有一些基本的數據類型,如 string 、 整型 、 浮點型 、 佈爾 等數據類型, Go語言中可以使用 type 關鍵字來定義自定義類型。

type是Go語法裡的重要而且常用的關鍵字,type絕不隻是對應於C/C++中的typedef。搞清楚type的使用,就容易理解go語言中的核心概念structinterface、函數等的使用。

2、類型定義

2.1 定義結構體

使用 type 可以定義結構體類型:

//1、定義結構體
//結構體定義
type person struct {
   name string //註意後面不能有逗號
   age  int
}

2.2 定義接口

使用 type 可以定義接口類型:

type USB interface {
 start()
 end()
}

2.3 定義其他的新類型

使用 type ,還可以定義新類型。

語法:

type 類型名 Type

示例代碼:

type myint int
type mystr string

func main() {

  var i1 myint
  var i2 = 100
  i1 = 100
  fmt.Println(i1)
  //i1 = i2 //cannot use i2 (type int) as type myint in assignment
  fmt.Println(i1,i2)
  
  var name mystr
  name = "王二狗"
  var s1 string
  s1 = "李小花"
  fmt.Println(name)
  fmt.Println(s1)
  name = s1 //cannot use s1 (type string) as type mystr in assignment
}

2.4 定義函數的類型

Go語言支持函數式編程,可以使用高階編程語法。一個函數可以作為另一個函數的參數,也可以作為另一個函數的返回值,那麼在定義這個高階函數的時候,如果函數的類型比較復雜,可以使用type來定義這個函數的類型:

func main() {
  res1 := fun1()
  fmt.Println(res1(10,20))
}


type my_fun  func (int,int)(string)

//fun1()函數的返回值是my_func類型
func fun1 () my_fun{
 fun := func(a,b int) string {
  s := strconv.Itoa(a) + strconv.Itoa(b)
  return s
 }
 return fun
}

3、類型別名

類型別名規定TypeAlias隻是Type的別名,本質上TypeAliasType是同一個類型。就像一個孩子小時候有小名、乳名,上學後用學名,英語老師又會給他起英文名,但這些名字都指的是他本人。

類型別名是 Go 1.9 版本添加的新功能。主要用於代碼升級、遷移中類型的兼容性問題。在 C/C++語言中,代碼重構升級可以使用宏快速定義新的一段代碼。Go 語言中沒有選擇加入宏,而是將解決重構中最麻煩的類型名變更問題。

type TypeAlias = Type

在 Go 1.9 版本之前的內建類型定義的代碼是這樣寫的:

type byte uint8
type rune int32


而在 Go 1.9 版本之後變為:

type byte = uint8
type rune = int32


這個修改就是配合類型別名而進行的修改。

4、類型定義和類型別名的區別

類型別名與類型定義表面上看隻有一個等號的差異,我們通過下面的這段代碼來理解它們之間的區別。

//類型定義
type NewInt int

//類型別名
type MyInt = int

func main() {
 var a NewInt
 var b MyInt
 
 fmt.Printf("type of a:%T\n", a) //type of a:main.NewInt
 fmt.Printf("type of b:%T\n", b) //type of b:int
}

結果顯示a的類型是 main.NewInt ,表示main包下定義的 NewInt 類型。b的類型是 int MyInt 類型隻會在代碼中存在,編譯完成時並不會有 MyInt 類型。

5、非本地類型不能定義方法

能夠隨意地為各種類型起名字,是否意味著可以在自己包裡為這些類型任意添加方法?

// 定義time.Duration的別名為MyDuration
type MyDuration = time.Duration
// 為MyDuration添加一個函數
func (m MyDuration) EasySet(a string) { //cannot define new methods on non-local type time.Duration
}
func main() {
}

以上代碼報錯。報錯信息:cannot define new methods on non-local type time.Duration

編譯器提示:不能在一個非本地的類型 time.Duration 上定義新方法。非本地方法指的就是使用 time.Duration 的代碼所在的包,也就是 main 包。因為 time.Duration 是在 time 包中定義的,在 main 包中使用。time.Duration 包與 main 包不在同一個包中,因此不能為不在一個包中的類型定義方法。

解決這個問題有下面兩種方法:

  • 將類型別名改為類型定義: type MyDuration time.Duration ,也就是將 MyDuration 從別名改為類型。
  • MyDuration 的別名定義放在 time 包中。

6、在結構體成員嵌入時使用別名

當類型別名作為結構體嵌入的成員時會發生什麼情況?

type Person struct {
 name string
}

func (p Person) Show() {
 fmt.Println("Person-->",p.name)
}

//類型別名
type People = Person

type Student struct {
 // 嵌入兩個結構
 Person
 People
}

func (p People) Show2(){
 fmt.Println("People------>",p.name)
}

func main() {
 //
 var s Student

 //s.name = "王二狗" //ambiguous selector s.name
 s.People.name = "李小花"
 s.Person.name = "王二狗"
 //s.Show() //ambiguous selector s.Show
 s.Person.Show()
 s.People.Show2()
 fmt.Printf("%T,%T\n",s.Person,s.People) //main.Person,main.Person

}

在通過s直接訪問name的時候,或者s直接調用Show()方法,因為兩個類型都有 name字段和Show() 方法,會發生歧義,證明People 的本質確實是Person 類型。

到此這篇關於Golang通脈之類型定義的文章就介紹到這瞭,更多相關Golang 類型定義內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: