環境準備
VSCode上で適当なワークスペースを用意した。 今回は「/Users/{わたし}/Documents/Projects/golang_introduction としてディレクトリを用意した。
golangのインストール
macOSを使用しているので、homebrewを使ってインストールする
bash1$ brew info go 2go: stable 1.11.1 (bottled), HEAD 3Open source programming language to build simple/reliable/efficient software 4https://golang.org 5Not installed 6From: /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/go.rb 7==> Requirements 8Required: macOS >= 10.10 ✔ 9==> Options 10--HEAD 11 Install HEAD version 12==> Caveats 13A valid GOPATH is required to use the `go get` command. 14If $GOPATH is not specified, $HOME/go will be used by default: 15 https://golang.org/doc/code.html#GOPATH 16 17You may wish to add the GOROOT-based install location to your PATH: 18 export PATH=$PATH:/usr/local/opt/go/libexec/bin 19==> Analytics 20install: 91,529 (30d), 265,569 (90d), 943,528 (365d) 21install_on_request: 64,960 (30d), 187,842 (90d), 594,605 (365d) 22build_error: 0 (30d) 23
brewで入る最新は1.11.2だった。1.11自体が2018/08リリースと割と新しいものだったのでこのままインストール
bash1$ brew install go 2
VSCodeについては .goファイルを作成してしまえばVSCodeからエクステンションのインストール案内が出るので そのままインストール。
入門
GOPATHの設定
bash1export GOPATH=/Users/{わたし}/Documents/Project/golang_introduction/ 2
golangはワークスペースプロジェクト単位で開発する。 基本的にコマンドやビルドを行う際にGOPATHを頼りに行うイメージかな? ディレクトリ(=プロジェクト)毎にGOPATHを設定したい等のニーズに答えるためにgoenvといったツールも用意されている。
Hello world
golang1package main 2 3import( 4 "fmt" 5) 6 7func main() { 8 fmt.Println("Hello world!") 9} 10
実行
bash1$go run hello_world.go 2Hello world! 3
疑問:importしている「fmt」って何?
フォーマットから取ったパッケージ。 基本的にはC言語でいう「print」や 「scan」にあたる関数を提供する。
コメント
golang1// 1行コメント 2 3/* 4複数行コメント 5 6*/ 7
import
golang1import ( 2 "fmt" 3 "math" 4) 5
こっちも可
golang1import "fmt" 2import "math" 3
ただし、こちらは推奨されないらしい。
exported name
golangでは名前の先頭が大文字のものは、外部から利用できる。
golang1package main 2 3import ( 4 "fmt" 5) 6 7func main() { 8 fmt.Println("Hello world!") 9} 10
この場合だとPrintlnがそれにあたる。
変数の定義
var で宣言して初期化する事が出来る。 型を明示的に指定する場合、intなどの型名は変数名の後に指定する。
golang1var x int = 10 2var y int = 20 3 4//こっちも可能 5var x,y int = 10,20 6
文字列の場合はダブルクォーテーションで括る
golang1var foo string = "bar" 2fmt.Println(foo) //bar 3
また、上記より短い宣言もできる
golang1var foo = "bar" 2
varという初期化子をつけて変数に値を代入した場合、型を省略できる。 省略された変数の型は、代入された値によって自動的に割り当てられる。 (型推論)
他に、:=を使って宣言する方法がある。
golang1foo2 := "bar" 2 3var num1 = 10 4num2 := 100 5
:= を使って宣言するのは型などをいい感じに認識してもらう「暗黙的宣言」という。 「暗黙的宣言」の場合は関数スコープ内でのみ利用が可能である。 つまり、関数の外では:=を使った暗黙的宣言はできない。
定数
最近のJavaScriptのように「const」をつけることで定数が宣言できる
golang1const message = "hello?" 2 3message = "Hi!" //エラー 4
定数(const)は、文字、文字列、boolean、数値でのみ使える。 定数の場合は := を使った宣言は利用できない。
ゼロ値
変数宣言時、何も値を指定しない場合、ゼロ値(zero value)が与えられる。 ゼロ値といっても数字の0(ゼロ)を入れるだけでなく、変数型によって異なる
- 数値型の場合(int/float) ... 0
- bool型の場合... false
- string型の場合... "" (空文字列)
この辺りはnull判定のときなどに活用できそうだ。
関数,function
よくある感じでOK。引数を指定する場合は上述の通り型が後。
golang1//func( [引数名] [型]) [戻り値の型] {} 2 3func main() { 4 calc(1,2) //3 5} 6 7func calc(a int, b int){ 8 var c int 9 c = a + b 10 fmt.Println(c) 11} 12
マルチプルリザルト
golangの特徴で、関数が複数の戻り値を返す事ができる。
golang1func main() { 2 a, b := swap("hello", "world") 3 fmt.Println(a, b) // hello__x world~~y 4} 5 6func swap(x, y string) (string, string){ 7 x += "__x" 8 y += "~~y" 9 return x, y 10} 11
if文
条件式は丸括弧()で括らない。
golang1func main() { 2 evaluation("test","test") //a==b 3 evaluation("test","hoge") //a!=b 4} 5 6func evaluation(a string, b string){ 7 8 if a==b { 9 fmt.Println("a==b") 10 }else{ 11 fmt.Println("a!=b") 12 } 13} 14
for文
よくあるfor文はこんな感じ。他の言語のように丸かっこ()で括る必要はない点に注意
golang1for i :=0; i < count; i++ { 2 fmt.Println(i) 3} 4 5//0 6//1 7//2 8//3 9//4 10//5 11//6 12//7 13//8 14//9 15
他の言語でいうwhileっぽいやり方も出来る
golang1var i = 0 2for i < count { 3 i++ 4 fmt.Println(i) 5} 6 7//0 8//1 9//2 10//3 11//4 12//5 13//6 14//7 15//8 16//9 17
無限ループ
golang1for { 2 fmt.Println("forever!") 3} 4
Array, 配列
配列は固定長。長さを変える事ができない。
golang1func main() { 2 var a [2]string 3 a[0] = "Captain" 4 a[1] = "America" 5 fmt.Println(a[0], a[1]) // Captain America 6 fmt.Println(a) // [Captain America] 7 8 primes := [6]int{2, 3, 5, 7, 11, 13} 9 fmt.Println(primes) //[2 3 5 6 11 13] 10} 11
個人的には変数そのものを出力するとカンマ区切りでなく スペース区切りになる点が気になる
スライス
こっちは可変長の配列だと思っていいらしい
golang1func main() { 2 3 names := [4]string{ 4 "John", 5 "Paul", 6 "George", 7 "Ringo", 8 } 9 fmt.Println(names) // [Joh Paul George Ringo] 10 11 a := names[0:2] 12 b := names[1:3] 13 fmt.Println(a, b) // [John Paul] [ Paul George] ...① 14 15 b[0] = "XXX" 16 fmt.Println(a, b) // [John XXX] [ XXX George] ...② 17 fmt.Println(names) // [John XXX George Ringo] 18} 19
他の言語もそうなのかもしれないけど、スライスは以下のような形で切り取って扱う事が出来る
①では、最初に0〜2を指定している。つまり、以下の範囲を指定したことになる。 つまり、John とPaulが出力対象
次に、1〜3を指定している。つまり、以下の範囲で、PaulとGeorgeが取扱の対象。
スライスは配列への参照のようなもの (らしい)
スライスは配列への参照のようなものです。 スライスはどんなデータも格納しておらず、単に元の配列の部分列を指し示しています。 スライスの要素を変更すると、その元となる配列の対応する要素が変更されます。 同じ元となる配列を共有している他のスライスは、それらの変更が反映されます。
②で取り扱っているのがまさにその部分。 一度スライスを他の変数に代入し、他の編集の値を書き換えたとしても、大元のスライスにもその変更が反映される。
/以上
よかったらシェアしてください!