Skip to content

golang tips

foolmacky edited this page Sep 11, 2021 · 10 revisions

■interface{}について

  • interface{}は実体は型情報と、データの実体or実体へのポインタの2つの値しか持っていない
  • 値が入るのか、ポインタが入るのかは、実体データの型によって異なる
    intならデータが入る。structは実体へのポインタが格納される
    なので、deep copyしてもあまり気にしなくても大丈夫
  • interface{}のポインタにはinterface{}としての機能が「無い」ため、デリファレンスする必要がある
package main
import log
type Person struct {
    Name string
}

func main() {
    p := Person{Name: "hoge"}

    iftest(p)
    iftestNull(nil)
    iftestNull()
}

//interface{}のタイプassertionはstructに関しても有効
func iftest(param interface{} {
    log.Println(param.(Person).Name)
}

func iftestNull(param interface{}) {
    if param == nil {
        log.Println("This is NULL")
    }
}

■type Interface

  • 異なるパッケージのinterfaceも満たすことができる
  • Interfaceを満たしている関数のリスナーをポインタ型にすると、そのStructのポインター変数しかインターフェースを満たさない。実体の変数はInterfaceを満たさない。
  • リスナーを実体にしていれば、両方満たす。
package main
import log

type PSample struct {
    name string
}

type Sample struct {
    name string
}

type AllStruct interface {
    Exec()
}

func (psample *PSample) Exec() {
    log.Println(psample.name)
}
//func (psample PSample) Exec() {
    //log.Println(psample.name)
//}
//同じ関数定義を、ポインターと実体の両方で定義することはできない

func main() {
    psample := &Psample{name: "psample"}
    sample := Sample{name: "sample"}
    var allstructs = []AllStruct{psample, sample}

    for _, sam := range allstructs {
        sam.Exec()
    }

    psample2 := Psample{name: "psample2"}
//実体を一度ポインタ変数に代入すれば、インターフェースを満たすことができる
    var ppsample2 = &psample2
    sample3 := &Sample{name: "psample3"}
//実体の場合はポインタ変数にしても「当然」インターフェースを満たすことができる
    var allstrct2 = []AllStruct{psample, sample, ppsample2, sample3}
    for _, sam2 := range allstruct2 {
        sam2.Exec()
    }
}

■pointer関連

■expert GO

https://www.slideshare.net/takuyaueda967/go-77689475

■go modulesの周辺

正規バージョンではなく、特定のコミットを使いたい場合の指定について

  • 特定のコミット指定をgo.modに記入するのは面倒くさい。その場合はgo getでコミットhashタグを指定して取得するとgo.modを自動で更新してくれる
go get \<リポジトリ\>@\<hashタグ\>
  • versionタグを付与していないパッケージの場合 go.modの記載ver.は通常v0.0.0-TIMESTAMP-hashだが、途中までver.タグが付与されていると必ずしもそうではない。go getしてgoに書き換えてもらうのが良い。

go buildの周辺

  • 利用しているライブラリがリポジトリ移動した場合のエラー
module declared its path as < new repository>
   but was requires as < old repository>
  • 参照しているソース自体、タグを含めて新しいリポジトリに移動していたとしても、そのタグが保持しているgo.modに古いリポジトリが設定されているとこのエラーが出る
  • 使うバージョンをgo.modも新しいリポジトリを指しているものに更新する

Clone this wiki locally