如何判斷Golang接口是否實現的操作

前言

在看一個底層庫的的時候,看到瞭一個比較奇怪的寫法,於是乎有瞭本文。

主要探討兩個問題:

1.利用編譯來判斷Golang接口是否實現

2.延伸出的make和new的區別

正文

1.利用編譯來判斷Golang接口是否實現

看瞭一個底層通用鏈接池的庫,有這麼一行代碼:

var _ Pooler = new(WeightedRoundRobin)

需要解釋的是:Pooler是一個接口類型。

type Pooler interface {
  // ...
}

剛開始看是疑惑的,為什麼new瞭之後是要拋棄調?

後面發現這個是為瞭驗證某某接口是否被實現瞭?

多看瞭一些代碼後發現很多地方有類似這樣的寫法。

至此Get到瞭。

解釋:如果說次接口沒有被實現,那麼一方面ide會有紅橫線出現,另一方面在編譯的時候會出現報錯。兩方面的提示來保證寫底層代碼的接口是有被實現的。

2.延伸出的make和new的區別

和小夥伴討論期間,跑出瞭這麼一個問題:“可以使用go test的方式,去_test.go文件中定義一個接口,來判斷就好瞭。上文判斷會存在浪費內存的情況”

這邊兩個點:

1.go test的方式肯定是可行的。

但是並沒法保證程序員會真的記住去執行進行檢測(非強制必須走的流程)。但是直接通過前文方式,是會在編譯的時候拋錯的,這個是必須走的流程,所以更推薦前文的方式。

2.new占內存?

new:申請瞭內存,但是不會將內存初始化,隻會將內存置零,返回一個指針。

make:申請瞭內存,返回已初始化的結構體的零值。

回到正文,雖然申請瞭內存,但占的內存其實並不多,並且在初始化後的一次gc中便會回收。所以還好。

同時也不存在效率問題,編譯型語言,你懂的。

同時驗證一個new和取地址和make的區別的代碼:

func main() {
 a1 := new([]int)
 a2:= &[]int{}
 a3:= make([]int,0)
 fmt.Println(a1,a2,a3,a1==a1)
}

輸出:

&[] &[] [] true

附錄:Golang new和 make的區別

擴展

對於內存的占用,今天看到一種寫法。

var _ Tester = (*Test)(nil)

這樣寫和new的區別在於:new是編譯的時候檢查,這樣寫是運行的時候檢查

補充:Golang接口實現多態

我就廢話不多說瞭,大傢還是直接看代碼吧~

package main 
import (
  "fmt"
)
 
func main() {
  user := &User{name: "Chris"}
  user.ISubUser = &NormalUser{}
  user.sayHi()
  user.ISubUser = &ArtisticUser{}
  user.sayHi()
}
 
type ISubUser interface {
  sayType()
}
 
type User struct {
  name string
  ISubUser
}
 
func (u *User) sayHi() {
  u.sayName()
  u.sayType()
}
 
func (u *User) sayName() {
  fmt.Printf("I am %s.", u.name)
}
 
type NormalUser struct {
 
}
 
func (n *NormalUser) sayType() {
  fmt.Println("I am a normal user.")
}
 
type ArtisticUser struct {
 
}
 
func (a *ArtisticUser) sayType() {
  fmt.Println("I am an artistic user.")
}
//RUN 之後輸出:
I am Chris.I am a normal user.
I am Chris.I am a artistic user.
//重用瞭sayName和sayHi方法,sayType方法可以多態來實現。

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。

推薦閱讀: