Go二三事

pardon110發表於2020-12-06

Go認為方法是新增了受限作用域型別的函式。本文介紹空結構體,空介面及指標型別強轉等瑣事。

receiver

Go稱之如下格式的函式為方法,recv為接收者變數

func (recv receiver_type) methodName(parameter_list) (return_value_list) {}

換而言之,若方法體內用不到類似其它語言中的this變數,可以這樣幹,但接收者型別不可略。

func (receiver_type) methodName(parameter_list) (return_value_list) {}

receiver_type 可以是任意型別,不僅僅是結構體型別
可以是介面型別,甚至是函式,int,bool,string,array的別名型別

package main
import "fmt"

type multiply int    

func (m multiply) tentimes() int {
    return int(m * 10)
}

func main() {
    var num int
    fmt.Print("Enter any positive integer: ")
    fmt.Scanln(&num)
    mul:= multiply(num)
    fmt.Println("Ten times of a given number is: ",mul.tentimes())
}

overloading

Go語言的方法過載是基於接收者型別的,以下這種形式是允許存在於同一包內

func (s *inclTax) Salary(e Employee) Employee
func (s *exclTax) Salary(e Employee) Employee

type

型別檢查

i := 10
reflect.TypeOf(i) // int

strconv 將字串轉為基本資料型別
其它可相容型別直接 type()強轉,或基於介面變數的型別斷言 .(type)

指標型別強轉有點特殊,需要用到unsafe.Pointer來解除指標在go中不可運算的限制。

package main

import (
    "fmt"
    "unsafe"
)

type A struct {
    name string
    age  int8
}

type B struct {
    notname string
    notage  int8
    sex     int8
}

func main() {
    b := &B{notname: "B", notage: 28, sex: 1}
    a := (*A)(unsafe.Pointer(b))
    fmt.Println(a.name) // B
}

interface vs struct

interfacestruct 都是Go關鍵字,用來輔助定義資料型別

  • struct 各個欄位型別集合體,本質是個具體值型別,可用作 map 鍵
  • interface 準確來說是個函式列表整合器,玩虛的,隱藏實現,具備行為截斷
    換而言之,介面未實現不可用,實現了該介面的變數也實現了(若存在)巢狀介面

struct{}

寬度描述了儲存一個資料型別例項需要佔用的位元組數
空結構體型別是沒有位段的結構體,換而言之它不佔用記憶體空間

    var p struct{}
    var s string                     
    fmt.Println(unsafe.Sizeof(p))    // prints 0
    fmt.Println(unsafe.Sizeof(s))    // prints 8

基於這些特性,常有以下應用場景

  • 空結構體作為方法的接收者
  • 空結構體寫入 chan 通道,作為觸發器,用其他冗餘資料的話,會影響程式效能

interface{}

與空結構體型別表示什麼都沒有,空介面型別簡而言之什麼都是
空介面interface{}比之如java 界的 object, 類似python中的 type 型別。
在什麼都是的情況下,看起來高大上,實際上淪為了工具,基本上就是成了容器,類js解構

func Printf(format string, a ...interface{}) (n int, err error)

這種型別不能直接讀寫,需要斷言存取實際具體型別,只不過傳輸時看起來無所不能。

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}

other

通常Go出於型別系統和記憶體管理的安全機制考慮,編譯器會對所有指標型別轉換或運算報錯,
但凡事沒絕對,有時的確有突破這方面的需求,故提供了 unsafe.Pointer包,一切操作都是可行。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章