1. 程式人生 > 實用技巧 >Golang基礎(三)

Golang基礎(三)

介面

【介面的概念】在Go語言中介面(interface)是一種型別,一種抽象的型別

【結構體實現介面方法】

package main

import "fmt"

type sayer interface {
	Say() string
} 

type Cat struct{}

func (c Cat) Say() string { 
	return "喵喵喵" 
}

func main() {
	var x sayer        // 宣告一個介面
	c := Cat{}         // 初始化一個結構體
	x = c               // 將結構體賦值給介面
	fmt.Println(x.Say()) // 介面就能夠呼叫結構體的方法了
}

  

【值接收者和指標接收者】

值接收者

package main

import "fmt"
type Mover interface {
	move()
}

type dog struct {}

func (d dog) move() {    // 值接收者
	fmt.Println("狗會動")
}

func main() {
	var x Mover	    // 宣告一個介面
	var wangcai = dog{} // 旺財是dog型別
	x = wangcai         // x可以接收dog型別
	x.move()
	var fugui = &dog{}  // 富貴是*dog型別
	x = fugui           // x可以接收*dog型別
	x.move()
}

----------------------------
狗會動
狗會動

指標接收者

package main

import "fmt"

type Mover interface {
	move()
}

type dog struct {}

func (d *dog) move() {	// 指標接收者
	fmt.Println("狗會動")
}

func main() {
	var x Mover
	var wangcai = dog{} // 旺財是dog型別
	x = wangcai         // x不可以接收dog型別
	var fugui = &dog{}  // 富貴是*dog型別
	x = fugui           // x可以接收*dog型別
}

--------------------------------------
編譯不通過:只能將指標型別賦值給介面,不能把值型別賦值給介面
cannot use wangcai (type dog) as type Mover in assignment:
dog does not implement Mover (move method has pointer receiver)

  

【介面巢狀】

// Sayer 介面
type Sayer interface {
	say()
}

// Mover 介面
type Mover interface {
	move()
}

// 介面巢狀
type animal interface {
	Sayer
	Mover
}

以上animal介面等價於

type animal interface {
    say()
    move()
}

  

【空介面】

空介面型別的變數可以儲存任意型別的變數

package main

import "fmt"

func main() {
	// 定義一個空介面x
	var x interface{}
	s := "Hello 沙河"
	x = s
	fmt.Printf("type:%T value:%v\n", x, x)
	i := 100
	x = i
	fmt.Printf("type:%T value:%v\n", x, x)
	b := true
	x = b
	fmt.Printf("type:%T value:%v\n", x, x)
}

  

空介面作為函式的引數:使用空介面實現可以接收任意型別的函式引數

// 空介面作為函式引數
func show(a interface{}) {
	fmt.Printf("type:%T value:%v\n", a, a)
}

  

空介面作為map的值:使用空介面實現可以儲存任意值的字典。

// 空介面作為map值
var studentInfo = make(map[string]interface{})
studentInfo["name"] = "沙河娜扎"
studentInfo["age"] = 18
studentInfo["married"] = false
fmt.Println(studentInfo)

  

【空介面型別斷言】:斷言就是猜空介面型別

x.(T)

x:表示型別為interface{}的變數
T:表示斷言x可能是的型別。

func main() {
	var x interface{}
	x = "Hello 沙河"
	v, ok := x.(string)
	if ok {
		fmt.Println(v)
	} else {
		fmt.Println("型別斷言失敗")
	}
}

斷言方法返回兩個引數,v表示x轉化為T之後的變數,ok表示猜的對不對,對則為true,錯則為false

如果確定斷言型別一定是正確的,可直接操作其值:

fmt.println(x.(string))

  

要進行多次斷言則用switch case語句

func justifyType(x interface{}) {
	switch v := x.(type) {
	case string:
		fmt.Printf("x is a string,value is %v\n", v)
	case int:
		fmt.Printf("x is a int is %v\n", v)
	case bool:
		fmt.Printf("x is a bool is %v\n", v)
	default:
		fmt.Println("unsupport type!")
	}
}

  

包Package

【包的概念】是多個Go原始碼的集合,是一種高階的程式碼複用方案。

【包的定義】

一個包可以簡單理解為一個存放.go檔案的資料夾。該資料夾下面的所有go檔案都要在程式碼的第一行新增如下程式碼,宣告該檔案歸屬的包。

package 包名

包名可以不和資料夾的名字一樣,包名不能包含 - 符號。(但package名稱一般都和資料夾名字一樣)
包名為main的包為應用程式的入口包,這種包編譯後會得到一個可執行檔案,而編譯不包含main包的原始碼則不會得到可執行檔案。

如果想在一個包中引用另外一個包裡的識別符號(如變數、常量、型別、函式等)時,該識別符號必須是對外可見的(public)。在Go語言中只需要將識別符號的首字母大寫就可以讓識別符號對外可見了。