doc.dev1x.org

Golang文法

プログラムのエントリーポイント

package main

import "fmt"

func main() {
    fmt.Println("Yeah!!") // Yeah!!
}

変数

var i int
var x, y, z int
var (
    x, y int
    name string
)
var i int = 0
// intと見なされる
i := 0
package main

import "fmt"

var msg string = "Yeah!!"  // パッケージ変数

func main() {
    fmt.Println(msg) // Yeah!!
}
package main

import "fmt"

func main() {
    var msg string = "Yeah!!"  // ローカル変数
    fmt.Println(msg) // Yeah!!
}

定数

const NAME = "yamada taro"
const NAME string = "yamada taro"

if文

if x == 1 {
    fmt.Println("x is 1")
}
var x int = 100
if x == 0 {
    fmt.Println("x is 0")
} else if x > 100 {
    fmt.Println("x is over 100")
} else {
    fmt.Println("other")
}
if x := f(); x == 1 {
    fmt.Println("x is 1")
}
if err := fn(); err != nil {
    // error handling.
}

switch文

switch animal {
case "dog":
    return "わおーん"
case "cat":
    return "にゃーん"
default:
    return "あ^〜"
}
switch animal {
case "dog":
    return "わおーん"
case "cat":
    fallthrough
case "bobcat":
    return "にゃーん"
default:
    return "あ^〜"
}
switch number {
case 1, 2:
    return "1 or 2"
case 3, 4:
    return "3 or 4"
default:
    return "0"
}

for文

// 無限にYeah!!を出力
for {
    fmt.Println("Yeah!!")
}
for i := 0; i < 100; i++ {
    fmt.Println(i)
    i++
}
for i := 0; i < 100; i++ {
    if i % 2 == 1 {
        continue
    }
    fmt.Println(i)
    i++
}
for i := 0; i < 100; i++ {
    fmt.Println(i)
    i++
    if i == 100 {
        break
    }
}
var numbers = [...]string{"One", "Two", "Three"}

for _, number := range numbers {
    fmt.Println(number)
}

パッケージ

package mypackage
package mypackage

const MAX = 99999  // 外部公開される定数
const name = "myname"  // 非公開の定数

// 公開される関数
func PublicFn() int {
    return 99999
}

// 非公開の関数
func privateFn() int {
    return 99999
}
import "mypackage"
import (
    "fmt"
    "mypackage"
)
import my "mypackage"  // myという別名を指定
import "mypackage/sub/sub1"

func main() {
    sub1.exec()
}
.
├── go.mod
├── go.sum
├── main.go
└── sub/
        └─ sub1/
            └─ sub2/
                └─ mod1.go
                └─ mod2.go
// mod1.go
package sub2

func Exec() string {
    return "にゃーん"
}
// mod2.go
package sub2

func Exec2() string {
    return "あ^〜"
}
// main.go
import "mypackage/sub1/sub2"

func main() {
    sub2.Exec()   // => にゃーん
    sub2.Exec2()  // => ^〜
}

関数

func fn(x int, y int) int {
    return x + y
}
func fn() {
    fmt.Println("Yeah!!") // Yeah!!
}
func fn() (int, int) {
    return 100, 1000
}
func fn() (int, int) {
    return 100, 1000
}

a, b = fn() //両方受け取る
_, b = fn() //1つ目の戻り値は破棄
a, _ = fn() //2つ目の戻り値は破棄
func fn(p ... int) {
    for i, _ := range p {
        fmt.Println(i)
    }
}

fn(1, 2, 3, 4, 5, 6) // 123456

無名関数

var fn = func() int {
    return 1000
}

fmt.Println(fn()) // 1000

特殊関数

var fn = func() int {
    return 1000
}

fmt.Println(fn()) // 1000
var fn = func() int {
    return 1000
}

fmt.Println(fn()) // 1000

defer

func f() {
    defer fmt.Println("1")
    fmt.Println("2")
}

f() // 2が出力された後、1が出力される
func f() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    fmt.Println("3")
}

f() // 3,2,1の順に出力される
func f() {
    file, err := os.Open("test.txt")
    if err != nil {
        return
    }
    defer file.close()
    fmt.Print(file)
}

f()

go

func main() {
    go task1()  // 並列実行
    go task2()  // 並列実行
    fmt.Println("run main")
}

func task1() {
    fmt.Println("run task1.")
}

func task2() {
    fmt.Println("run task2.")
}
ch := make(chan int)
package main

import "fmt"

func main() {
    channel := make(chan int)  // channelを作成
    defer close(channel)  // 使い終わったchannelはCloseする必要がある模様
    go task(channel)  // task関数の引数としてchannelを渡す
    result := <- channel  // channelから並行実行された関数のデータを取得
    fmt.Println(result)  // 9999999
}

func task(channel chan int) {
    channel <- 9999999 // channelにデータを書き込み
}

struct

type Person struct {
    name string
    age int
}
type Person struct {
    Name string  // 公開フィールド
    age int      // 非公開フィールド
}
type Person struct {
    name string
    age int
}

// フィールドの定義順に値を入力
var p Person = Person{
    "Jhon",
    30
}

// フィールドの名前ベースで値を入力
var p Person = Person{
    name: "Jhon",
    age: 30
}
type Person struct {
    name string
    age int
}

func (p *Person) IsAdult() bool {
    if p.age >= 18 {
        return true
    } else {
        return false
    }
}

// フィールドの名前ベースで値を入力
var p Person = Person{
    name: "Jhon",
    age: 30
}

result := p.IsAdult()
fmt.Println(result) // true

interface

type MyInterface interface {
    MyMethod() string
}
type MyInterface interface {
    MyMethod() string
}

type MyStruct1 struct {
    value string
}

// MyMethodを持っているのでMyInterfaceを実装しているものと見なされる
func (s *MyStruct1) MyMethod() string {
    return s.value
}
var mystruct MyInterface = &MyStruct1{"Yeah!!"}  // ポインタを返す必要がある模様
result := mystruct.MyMethod()
fmt.Println(result) // Yeah!!
package main

import "fmt"

type MyInterface interface {
    MyMethod() string
}

type MyStruct1 struct {
    value string
}

func (s *MyStruct1) MyMethod() string {
    return s.value
}

func main() {
    var mystruct MyInterface = &MyStruct1{"Yeah!!"}  // 変数の型はMyInterfaceだが実体はMyStruct1
    result := mystruct.MyMethod()
    fmt.Println(result) // Yeah!!
}

基本型

interface{}型

var x interface{}  // xにはあらゆる型のデータを代入可能
var x interface{}
x = 100
val, ok := x.(int)  // valにint型の変数okにキャスト可能かどうかの真偽値が返る
var x interface{} = 100

switch val := x.(type) {
case int:
    fmt.Println("Int")
case string:
    fmt.Println("String")
default:
    fmt.Println("Other")
}

ポインタ

package main

import "fmt"

func main() {
    var val1 int = 1000
    var val2 *int = &val1   // val2はポインタ型変数として宣言されval1のアドレスを参照している

    fmt.Println(val1)       // => 1000
    fmt.Println(val2)       // => 実行時のメモリアドレス
}

参照渡しと値渡し

package main

import (
    "fmt"
)

func main() {
    a, b := 10, 10
    called(a, &b) // aはそのままbはアドレス演算子をつけて呼び出す
    fmt.Println("値渡し:", a)
    fmt.Println("参照渡し:", b)
}

func subfn(a int, b *int) {
    a = a + 1 // 変数をそのまま変更
    *b = *b + 1 // 変数の中身を変更
}
値渡し:10
ポインタ渡し:11

配列

var myArray [3]int // 要素数が3intの値を持つ配列を宣言
myArray[0] = 10  // インデックスで代入/参照が可能
var myArray [3]int = {10, 20, 30}
var myArray [...]int = {10, 20, 30, 40, 50}
var myArray [...]int = {10, 20, 30, 40, 50}
myArray2 := myArray
myArray2[0] = 999 // myArray2の0番は999になるがmyArrayのデータは影響を受けない

Slice

var 変数名 []
var 変数名 [] = [] {初期値1, ... 初期値n}
変数名 := [start:end]
package main

import "fmt"

func main() {
    var slice1 []string
    fmt.Println(slice1)         // []

    var slice2 []string = []string {"一", "二", "三"}
    fmt.Println(slice2)         // ["一", "二", "三"]

    var slice3 := slice2[0:1]
    fmt.Println(slice3)         // ["一"]
}

Map

var m1 map[string] string = map[string]string {}
m2 := make(map[string]string)
m3 := map[string]string{}
m := map[string] string {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}
m := make(map[string]string)
m["key1"] = "value1"
m["key2"] = "value2"
m["key3"] = "value3"
delete(m, "key1")
_, ok := m["key100"]

if ok {
    fmt.Println("exist.")
} else {
    fmt.Println("not exist.")
}
m := map[string] string {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}

for key, value := range m {
    fmt.Printf("%s=%d\n", key, value)
}

type(型エイリアス)

type MyInt int
var i MyInt = 5
// string:interface{}で構成されるMapにConfigMapという別名を付けた
type ConfigMap map[string] interface{}

conf := ConfigMap {
    "APP_NAME": "App1",
    "DEBUG": true,
    "VERSION": 1
}

conf["APP_NAME"]    // App1

参考資料