カテゴリー: go

  • Go 開発環境: GOROOT、GOPATH、および VSCode 設定の理解

    Go 開発環境: GOROOT、GOPATH、および VSCode 設定の理解

    Go の開発環境を設定する際に、特に VSCode や asdf を使用する場合は、GOROOTGOPATH の役割を理解し、正しく設定することが重要です。
    この記事では、これらのコンポーネントとその関係を整理し、スムーズな開発環境を実現するための設定方法を説明します。

    GOROOT: Go のインストールディレクトリ

    定義: GOROOT は、Go がインストールされているディレクトリを指す環境変数です。Go のバイナリ、標準ライブラリのソースコード、およびコンパイラツールが含まれています。

    目的: GOROOT は Go のツールチェーンに対して、コアライブラリやバイナリの場所を教える役割を果たします。Go をインストールすると自動的に設定されるため、通常は変更する必要はありません。ただし、複数の Go バージョンをインストールしている場合は設定が必要です。

    :

    • asdf を使って Go のバージョン 1.22.1 をインストールした場合、GOROOT は次のようになります。

      /Users/your.name/.asdf/installs/golang/1.22.1/go

    GOPATH: ワークスペースディレクトリ

    定義: GOPATH は、Go のコード、依存関係、およびバイナリが保存されるワークスペースのルートを指定する環境変数です。

    目的: GOPATH は、Go のツールチェーンに対してプロジェクトのソースコードやサードパーティパッケージのインストール場所を教えます。GOROOT とは異なり、GOPATH は任意のディレクトリに設定できます。

    :

    • 一般的な GOPATH の設定は次のようになります。

      /Users/your.name/go

    VSCode 設定: GOROOT と GOPATH の設定

    VSCode を使用して Go の開発を行う場合、エディタに対して Go のインストール場所(GOROOT)とワークスペース(GOPATH)を知らせる設定が必要です。

    VSCode 設定:

    • go.goroot: この設定は VSCode に Go のインストール場所を教えます。asdf が管理する Go のインストールパス内の go ディレクトリを指す必要があります。
    • go.gopath: この設定は VSCode に Go のワークスペースの場所を教えます。GOPATH に設定したディレクトリを指します。

    設定例:

    { "go.gopath": "/Users/your.name/go", "go.goroot": "/Users/your.name/.asdf/installs/golang/1.22.1/go" }

    なぜ GOROOT と GOPATH は異なるパスなのか?

    GOROOTGOPATH は異なる目的を持つため、別々のパスを設定する必要があります。

    • GOROOT は Go のインストール自体を指します。Go コンパイラ、標準ライブラリ、ツールチェーンが含まれています。
    • GOPATH は個人の Go ワークスペースを指します。プロジェクトのソースコード、ダウンロードした依存関係、ビルドしたバイナリが含まれます。

    asdf を使用すると、複数の Go バージョンを管理できますが、それぞれのバージョンに対して GOROOT が異なります。一方、GOPATH は一貫して個人のワークスペースを指します。

    実際の設定例: 環境のセットアップ

    1. Go のインストール(asdf を使用):
      asdf install golang 1.22.1
      asdf global golang 1.22.1
    2. 環境変数の設定: シェルの設定ファイル(~/.bashrc, ~/.zshrc など)に以下を追加します。

      export GOROOT=$HOME/.asdf/installs/golang/1.22.1/go export GOPATH=$HOME/go export PATH=$GOROOT/bin:$PATH
    3. VSCode の設定: settings.json を開き、次の設定を追加します。

      { "go.gopath": "/Users/your.name/go", "go.goroot": "/Users/your.name/.asdf/installs/golang/1.22.1/go" }

    結論

    GOROOTGOPATH の違いと、それを VSCode に設定する方法を理解することは、スムーズな Go 開発環境を構築するために非常に重要です。これらのパスを正しく設定することで、Go のツールやエディタが必要なファイルや依存関係を正しく見つけることができ、設定に関連するエラーのリスクを減らすことができます。

    詳細については、公式の Go ドキュメント「Go 開発環境のセットアップ」を参照してください。

  • File is not `goimports`-ed with -local github.com/xxx/xxx (goimports)

    golangci-lint run ./...
    

    実行時、

    File is not `goimports`-ed with -local github.com/xxx/xxx (goimports)
    

    というエラーが発生することがあったのでその対処法を紹介

    (さらに…)
  • SA1019: “io/ioutil” has been deprecated since Go 1.16: As of Go 1.16

    SA1019: "io/ioutil" has been deprecated since Go 1.16: As of Go 1.16
    

    と引っかかるようになった場合の対処として、旧Version (左)で記載していた書き方を、現時点での推奨(右)に書き換える必要がある。

    非推奨(deprecated)推奨
    ioutil.Discardio.Discard
    ioutil.NopCloser()io.NopCloser()
    ioutil.ReadAll()io.ReadAll()
    ioutil.ReadDir()os.ReadDir()
    ioutil.ReadFile()os.ReadFile()
    ioutil.TempDir()os.MkdirTemp()
    ioutil.TempFile()os.CreateTemp()
    ioutil.WriteFile()os.WriteFile()

    参考情報

    https://text.baldanders.info/golang/deprecation-of-ioutil/

  • 【解決法】go1.16でビルドエラー「no required module provides package github.com」が発生する場合

    【解決法】go1.16でビルドエラー「no required module provides package github.com」が発生する場合

    go1.16 で golang を書いて build すると、タイトル通りのエラーが表示された。

    調べてみると go 1.15 までは go buildgo test などのコマンドを実行すると、 go.modgo.sum の内容をよしなに更新されていたが、go 1.16 からは自動では更新されなくなったようだ。

    これを解決するには

    $ go mod tidy

    とすることで、go のモジュールに書かれている不足分のパッケージを go.mod に書き込んでくれる

    % go build -o hoge.go
    main.go:7:2: no required module provides package github.com/hackebrot/turtle; to add it:
            go get github.com/hackebrot/turtle
    
    
    % go mod tidy
    go: finding module for package github.com/hackebrot/turtle
    go: downloading github.com/hackebrot/turtle v0.1.0
    go: found github.com/hackebrot/turtle in github.com/hackebrot/turtle v0.1.0
    go: finding module for package github.com/hackebrot/go-repr/repr
    go: finding module for package github.com/google/go-cmp/cmp
    go: downloading github.com/google/go-cmp v0.5.5
    go: downloading github.com/hackebrot/go-repr v0.1.0
    go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.5.5
    go: found github.com/hackebrot/go-repr/repr in github.com/hackebrot/go-repr v0.1.0
    
    % go build -o hoge.go
    

    参考情報

    https://golang.org/ref/mod#go-mod-tidy

  • go言語で自分のlocalIPを取得する

    go言語で自分のlocalIPを取得する

    はじめに

    dockerコンテナでgoのプログラムを動かしていると、コンテナのIPをどのように取得すればよいか困ったのでその対処を紹介。

    コード

    package main
    
    import (
    	"fmt"
    	"net"
    )
    
    func main() {
    
    	netInterfaceAddresses, _ := net.InterfaceAddrs()
    
    	for _, netInterfaceAddress := range netInterfaceAddresses {
    
    		networkIp, ok := netInterfaceAddress.(*net.IPNet)
    
    		if ok && !networkIp.IP.IsLoopback() && networkIp.IP.To4() != nil {
    
    			ip := networkIp.IP.String()
    
    			fmt.Println("Resolved Host IP: " + ip)
    
    		}
    	}
    }

    解説

    至ってシンプル。 “` net.InterfaceAddrs() “` でIPを取得することが可能だ。

    127.0.0.1 で表現できない時など、テストコードなどで活躍しそう。

  • go言語で設定ファイルを簡単に読み込む

    go言語で設定ファイルを簡単に読み込む

    はじめに

    go言語で設定ファイルを読み込む際、https://gopkg.in/ini.v1 というのがとても便利だったため紹介。

    これを使う事で、Configファイルに記載したパラメータを簡単にgoで使う事ができる。

    インストール

    https://gopkg.in/ini.v1

    を参考に、

    go get gopkg.in/ini.v1
    でインストールが可能。

    goでconfigファイルを読み込む

    サンプルのファイルを見ながらだと理解しやすいと思うので、コードをベースに紹介。

    読み込むconfigファイル

    [web]
    port = 443
    
    [db]
    name = oreoredb
    user = userA

     よくある形式。

    読み出すgoはこのような感じに記載

    package main
    
    import (
    	"fmt"
    	"gopkg.in/ini.v1"
    )
    
    type Config struct{
    	Port int
    	Db string
    	User string
    }
    
    var Cnf Config
    
    func init(){
    	c, _ := ini.Load("config.ini")
    	Cnf = Config{
    		Port: c.Section("web").Key("port").MustInt(),
    		Db: c.Section("db").Key("name").MustString("hogehoge.sql"),
    		User: c.Section("db").Key("user").String(),
    	}
    }
    
    func main(){
    	fmt.Printf("%v \n", Cnf.Port)
    	fmt.Printf("%v \n", Cnf.Db)
    	fmt.Printf("%v \n", Cnf.User)
    }

    結果

    $ go run read.go
    443 
    oreoredb 
    userA

    簡単に取り出す事ができた。

    詳細の使い方はこちら

    https://godoc.org/gopkg.in/ini.v1

     

    golang の新書

  • go言語でランダムな数値を出力させる

    go言語でランダムな数値を出力させる

    はじめに

    go言語でランダムな数値を出力させる

    コード

    package main
    
    import "math/rand"
    import "time"
    import "fmt"
    
    func main() {
        rand.Seed(time.Now().Unix())
        
        for i := 1; i <= 10; i++ {
            fmt.Println(rand.Intn(10))
        }
    }

    結果

    darkenergy:tmp sumito$ go run random.go
    4
    6
    3
    1
    7
    9
    3
    3
    1
    8
    darkenergy:tmp sumito$

     内訳

    rand.Intnは、randパッケージに新しい乱数を生成するとき、同じ初期化 rand.NewSource(1) を使っている。 これをUnixtimeをシードとしてあたえる事で、異なる乱数を出す事ができる。

    参考情報

    https://qiita.com/makiuchi-d/items/9c4af327bc8502cdcdce http://www9.plala.or.jp/sgwr-t/lib/srand.html

    golang の新書

  • go言語でgracefulを使ってwebサーバを立てる

    go言語でgracefulを使ってwebサーバを立てる

    はじめに

    gracefulというパッケージがあるので、これを利用することで簡易的にwebサーバを立ち上げることができる。

    これを使えばApacheやNginxを使わずとも、go言語だけでwebサーバを立ち上げることができるのでその方法を紹介。

    gracefulを利用する

     

    まずはgo get

    go get gopkg.in/tylerb/graceful.v1

    その後、.goを作成する。

    手順は README.md より抜粋

    package main
    
    import (
      "gopkg.in/tylerb/graceful.v1"
      "net/http"
      "fmt"
      "time"
    )
    
    func main() {
      mux := http.NewServeMux()
      mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        fmt.Fprintf(w, "Welcome to the home page!")
      })
    
      graceful.Run(":3001",10*time.Second,mux)
    }

    とりあえずコピペでよい。

    起動

    go run greaceful.go

    ブラウザで

    http://localhost:3001/

    へ接続

    これは非常にシンプルな例だが、API作成などに非常に役立ちそう。

     

     

  • go言語でファイルを書き出す

    go言語でファイルを書き出す

    はじめに

    ファイルを開き、書き出す方法

    自分用メモ

    コード

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    	"log"
    )
    
    func main() {
    
    	// file open
    	content, err := ioutil.ReadFile("main.go")
    	if err != nil {
    		log.Fatalln(err)
    	}
    	fmt.Println(string(content))
    
    	// file 書き出し
    	if err := ioutil.WriteFile("tmp", content, 0755); err != nil {
    		log.Fatalln(err)
    	}
    }

    結果

    $ ls -l /Users/sumito/go/src/github.com/GitSumito/go-sample/tmp
    -rwxr-xr-x  1 sumito  staff  306  5 14 00:00 /Users/sumito/go/src/github.com/GitSumito/go-sample/tmp
    $

     

    golang の新書

  • go言語でのstringやint、structのsort

    go言語でのstringやint、structのsort

    はじめに

    どの言語でも一発でsortするメソッドは用意されているものだが、あまり馴染みのない言語だと時間がかかるものだ。
    go言語でのsortについてまとめる。

    以下、自分用メモ。

    コード

    package main
    
    import (
    	"fmt"
    	"sort"
    )
    
    func main() {
    
    	i := []int{5, 3, 2, 8, 7}
    	s := []string{"c", "a", "z"}
    
    	p := []struct {
    		Name  string
    		Point int
    	}{
    		{"AAA", 50},
    		{"BBB", 40},
    		{"CCC", 10},
    		{"DDD", 20},
    	}
    
    	// Intをsort(昇順)
    	sort.Ints(i)
    	fmt.Println(i)
    
    	// stringをアルファベット順にsort
    	sort.Strings(s)
    	fmt.Println(s)
    
    	// structをStringでsort (名前順)
    	sort.Slice(p, func(i, j int) bool { return p[i].Name < p[j].Name })
    	fmt.Println(p)
    
    	// structをIntでsort (昇順)
    	sort.Slice(p, func(i, j int) bool { return p[i].Point < p[j].Point })
    	fmt.Println(p)
    
    }

    出力結果

    [2 3 5 7 8]
    [a c z]
    [{AAA 50} {BBB 40} {CCC 10} {DDD 20}]
    [{CCC 10} {DDD 20} {BBB 40} {AAA 50}]

     

    golang の書籍

    golang の書き方ではなく、お作法を学ぶことができる良書。