1. 程式人生 > 其它 >Go語言中介面相關知識點彙總

Go語言中介面相關知識點彙總

  最近公司有專案需要使用go語言來重構以前用php編寫的專案,我其實對go沒啥興趣,但是為了生活,只能啃起來了,這裡借`狂神`的名言,與君共勉吧!

  ---------

  只要學不死,就往死裡學! ----狂神

  ---------

  介面的定義

  在支援面向物件的語言裡,基本上都有介面概念, 介面的定義:它是定義一個物件的行為,具體的實現細節,由物件本身確定

  介面的關鍵字:interface

  介面的宣告與實現

  //宣告 一個介面

  type Person interface{

  eat()

  }

  //建立一個結構體,模擬一個類,在go語言中沒有class的概念!

  type Man struct{

  name string

  }

  //這裡是Man型別實現了接口裡的方法eat(),也就可以說它實現了介面(這裡需要全部實現了接口裡的方法,才是實現了介面)

  func (p Man) eat() {

  fmt.Println(p.name,",有好吃的嗎?")

  }

  //實現

  func main() {

  var v Person

  man :=Man{name: "test"}

  //這裡注意,由於man是實現了Person的介面,要不是會報錯的

  v=man

  v.eat()

  }

  總結

  //1.go裡面沒有implement關鍵字

  //2.只要是型別實現了接口裡的所有方法,就可以說是它是實現了這個介面

  實際應用

  //舉個實際中的例子,在專案裡,我們有個一個針對不同等級的會員,積會計算的方式會有些不同,這個場景是非常合適用介面來解決的,

  //定義一個計算積分的介面,不同的等級會員都實現自己的計算方法就可以

  //定義一個計算積分的介面

  type CalcPoint interface{

  calc() float64

  }

  //定義一個普通會員的結構體

  type ComMember struct{

  name string

  score float64

  }

  func (c ComMember) calc() float64 {

  return c.score+10

  }

  //定義一個高階會員的結構體

  type GoldMember struct{

  name string

  score float64

  }

  func (g GoldMember) calc() float64 {

  return g.score+20

  }

  //這裡就簡化了,這裡做個無用功能吧,就是計算下,所有人的積分總和是多少

  //定義一個接收calcPoint型別引數的 函式

  func getTotalScore(members []CalcPoint) {

  total :=0.00

  for _, member :=range members {

  total=total+member.calc()

  }

  fmt.Println("總積分",total)

  }

  func main() {

  //建立一個普通會員

  member1 :=ComMember{

  name: "ton",

  score: 78,

  }

  //建立一個高階會員

  member2 :=GoldMember{

  name: "uzi",

  score: 89,

  }

  members :=[]CalcPoint{member1,member2}

  getTotalScore(members) // 返回值197

  }

  空介面

  空介面:沒有包含方法的介面,所以在go語言中,所有的型別都是空介面

  表示方法:interface{}

  型別斷言

  //型別斷言

  i.(T) //介面i的具體型別T

  //

  func main(){

  var s interface{}="abc"

  a,ok :=s.(string)//a=>值,ok,如果斷言成功,返回true,否則返回false

  fmt.Println(a,ok)

  }

  //使用switch case進行型別選擇

  func findType(i interface{}){

  switch i.(type){ //注意這裡i.(type)

  case int:

  fmt.Println("int")

  case string:

  fmt.Println("string")

  case float64:

  fmt.Println("float64")

  default:

  fmt.Println("沒有找到")

  }

  }

  實現介面的方法:指標接收者和值接收者

  結論

  如果接收者型別為指標,則接收者的值只能是指標

  如果接收者型別為值型別,則接收者的值可以是指標或者是值

  程式碼說明

  package main

  import "fmt"

  type notifier interface{

  notify()

  }

  func sentNotify(n notifier) {

  n.notify()

  }

  type User struct{

  name string

  }

  func (u *User) notify() {//這裡的值是指標型別接收者

  fmt.Println("user中的notify")

  }

  //如果這個值是值型別接收者時,在呼叫這個sentNotify()函式傳引數時,可以是指標型別或者是值型別都可以

  func (u User) notify() {//這裡的值是指標型別接收者

  fmt.Println("user中的notify")

  }

  func main() {

  u:=User{

  name: "abc",

  }

  //sentNotify(u)//這裡是報錯的 cannot use u (type User) as type notifier in argument to sentNotify:

  // User does not implement notifier (notify method has pointer receiver)

  //這意思也是說 這個介面方法接收指標型別的值,你給一個值型別的引數是不可以的

  //需要傳指標型別的值

  sentNotify(&u)

  }