赶紧学习Golang

关于

这是为那些有其他语言经验的人和想要学习Golang的人提供的一个快速学习基本语法的总结。

你好,世界

首先是基本的“你好世界”。

package main

import "fmt"

func main() {
    fmt.Println("Hello, World")
}

Go Playground

把以下内容用汉语进行本地化解释,只需要一个选项:

包裹

所有的非main包必须与目录结构一致。

软件包声明

package pkg

导入

引入包(package)的导入

import "pkg"

也可以同时导入多个包。可以使用“标准包”,“工作空间上的包”和“本地(相对路径)”来导入。

import (
    "pkg"
    "pkg/sub"
    a "abc" // 別名でのimport
    . "def" // ドットでのimport(package名を省略できる
    _ "ghi" // ブランクでのimport(init関数だけ実行され, packageは使用できない)

)

导出

在顶级声明的情况下,可从其他包中使用“函数/方法”、“变量/常量”和“类型”。然而,它们需要以大写字母开头。

type Hoge struct {
    Name string // public扱い
    age int     // private扱い
}

func Hello() {
    fmt.Println("public扱い外部から使用できる")
}

func hello() {
    fmt.Println("private扱い外部から使用できない")
}

初始化函数

用于执行一次的特殊函数,用于初始化package(在程序执行时首先被调用)。它可以有多个定义但调用顺序是不确定的。

func init() {
    fmt.Println("init1")
}

func init() {
    fmt.Println("init2")
}

内部

供应商

基础语法

评论 tǐ)

// 行コメント
/*
ブロックコメント
*/

行末

基本上,將換行視為行尾處理。即使是「;(分號)」也是行尾。

var v1 = 1
var v2 =
    2

鉴别符号

用中文进行翻译的一种方式如下:
与基本的编程语言相同的([a-zA-Z_][a-zA-Z_0-9]*). 为了防止错误,明确规定不使用一个下划线的特殊(空白)标识符。

var _ = 100
v, _ := Func() // 2個目の戻り値は使わない

– 类型

基本型 – 原生地在中文中改述 。

種類型名サイズ符号デフォルト値説明整数int4/8○0符号付き整数. サイズはCPU依存〃int81○0int(8ビット)〃int162○0int(16ビット)〃int324○0int32(ビット)〃int648○0int64(ビット)〃uint4/8○0符号なし整数. サイズはCPU依存〃uint81×0uint(8ビット)〃uint162×0uint(16ビット)〃uint324×0uint(32ビット)〃uint648×0uint(64ビット)〃byte1×0uint8の別名〃rune4○0int32の別名. Unicodeコードポイントを格納〃uintptr-×0ポインタの値を数値で格納. サイズはCPU依存浮動小数点数float324-0.032ビット浮動小数点数(IEEE754準拠)〃float648-0.064ビット浮動小数点数(IEEE754準拠)複素数complex648-0.0float32の実数と虚数を持つ複素数〃complex12816-0.0float64の実数と虚数を持つ複素数文字列string–“”文字列を格納真偽値bool–false真(true)または偽(false)を格納

多功能的

種類型名説明配列[n]T固定長配列スライス[]T可変長配列ポインタ*Tアドレスを格納マップmap[Tk] Tvマップ(key-value)のペアを格納チャネルchan T並列処理時の通信用関数func(T1)T2関数を格納構造体struct{ … }構造体(フィールドの集合)interfaceinterface{ … }インターフェース(メソッドの集合)

变量声明

谷歌的Go语言的变量声明

    • 型名が変数名のあと(var 変数名 型名)

 

    • varキーワードを使う(:=で省略可能)

 

    型推論できる
var v1 int      // 初期値なし(デフォルト値で初期化)
var v2 int = 10 // 初期値あり
var v3     = 10 // 型の省略(初期値の指定の必要あり)
var v4, v5 int          // 複数の変数(初期値なし) 
var v6, v7 int = 10, 20 // 複数の変数(初期値あり)
var v8, v9     = 10, 20 // 複数の変数(型省略)
var v10, v11 = func() // 戻り値が2個の関数

var ( // まとめて宣言
    v12 int = 100
    v13     = 200
)

v14 := 300 // var v14 = 300と同じ

文字

// 整数リテラル(int型)
dec := 1234
oct := 01234 
hex := 0xabc

// 浮動小数点リテラル(float64型)
f1 := 1.2
f2 := 1.2e-2 // 指数表記

// 虚数リテラル(complex128型)
i1 := 1.2i
i2 := 1.2i+3
i3 := complex(1.2, 2.3) // 組み込み関数complexで複素数を作成
real(i3) // 組み込み関数realで実数部を取得
imag(i3) // 組み込み関数imagで虚数部を取得

// 文字
r := 'a' // rune(Unicodeコードポイント)文字
s := "abcdefg" // 文字列
raw := `abcd
efg` // raw(生)文字列

// 複合リテラル
v1 := [3]int {1,2,3} // 配列
v2 := []int {1,2,3} // スライス
v3 := map[string]int {"a":1} // マップ
v4 := struct{ a int} {a: 1} // 構造体

// 関数リテラル
f := func(a int) int {return a}
f(3)

固定的数量

const (
    c1 uint = 1 // uint型
    c2 = c1     // uint型
    c3 = 3      // 型なし
)

const (
    u1 uint = 1 // 1
    u2      = 1 // 1
    u3      = 1 // 1
)

忽略微小的东西。

可以创建类似于enum的连续值常量。

package main

import (
    "fmt"
)

const (
    a0     = iota       // 0
    a1     = iota       // 1
    a2     = 10         // 10
    a3     = iota       // 3(iotaの値は()内での行数で決まる)
    a4, a5 = iota, iota // どちらも4
)

const (
    b0 = iota        // 0
    b1               // 1(省略可能. 1行目のiota式を使用)
    b2               // 2(〃)
    _                // 3(ブランクによるスキップ
    b3               // 4
    b4 = iota * iota // 25(5*5)
)

const (
    c0 = 1 << iota // 1(1 << 0)
    c1             // 2(1 << 1)
    c2             // 4(1 << 2)
    c3             // 8(1 << 3)
)

func main() {
    fmt.Println(a0, a1, a2, a3, a4, a5)
    fmt.Println(b0, b1, b2, b3, b4)
    fmt.Println(c0, c1, c2, c3)
}

Go Playground

演员阵容

v1 := int64(100)    // int->int64
s1 := []byte("abc") // string->[]byte
s2 := string(s1)    // []byte->string

条件分岐,也称为if语句。

Golang的if语句

    • ()で条件式を囲わない

 

    • 条件式は真偽値型でなくてよい

 

    • else if/elseは前の条件ブロック{}の後に書く. 改行しない

 

    if文(elseブロックの最後まで)だけのスコープを持つ変数を宣言できる(他の制御構文も同様)
if 条件式1 {
    // 条件式1がtrueのとき実行
} else if 条件式2 {
    // 条件式2がtrueのとき実行
} else {
    // それ以外のとき実行
}

// if文での変数宣言
// 初期化文で使える文
    // 変数宣言(:=), 代入文, ++, --, 関数, メソッド呼び出し, チャンネル送信・受信
if 初期化文; 条件式1 {
    ...
} else if 初期化文; 条件式2 {
    ...
} else {
    ...
} // スコープはここまで

条件分岐(switch语句)

Golang的switch语句

    • break文を書かなくても次のcaseが実行されない(実行するにはfallthrough文を使う)

 

    case文に条件式を書くこともできる(trueの場合実行)
switch 式1 {
case 式2:
    ...
case 式3, 式4:
    // 式3と式4のいずれかと一致した場合実行
    ...
case 式5:
    ...
    // 次のcaseも実行される
    fallthrough
case 式6:
    ...
default:
    ...
}

switch { // ここには式を書かない
case 条件式1:
    ...
case 条件式2:
    ...
default:
    ...
}

Go Playground

循环(for循环)

Golang的for循环

    • 繰り返しはfor文だけ(while文/do while文はない)

 

    • 基本はC言語などと同じ

 

    • 多重for文はラベル指定のbreak文/continue文で抜ける(goto文でも可能)

 

    拡張for文(foreach)は組み込み関数rangeを使う
for 初期化文; 条件式; 更新処理文 {
    ...
}

// 条件式のみ(while)
for 条件式 {
    ...
}

// 無限ループ
for {
    ...
}

// ラベルで外部ループにジャンプ
Loop:
for ... {
    for ... {
        if ... {
            continue Loop
        }
        if ... {
            break Loop
        }
    }
}
package main

import (
    "fmt"
)

func main() {
    // 文字列
    // 第1変数:バイト単位の位置
    // 第2変数:rune(Unicodeコードポイント)
    s := "hoge"
    for i, c := range(s) {
        fmt.Println(i, string(c)) // rune->string
    }

    // 配列・スライス
    // 第1変数:インデックス
    // 第2変数:要素
    a := []int {1,3,5}
    for i, v := range(a) {  
        fmt.Println(i, v)
    }

    // マップ
    // 第1引数:キー
    // 第2引数:バリュー
    m := map[string]int {"a":1, "b":2, "c":3}
    for k, v := range(m) {
        fmt.Println(k, v)
    }

    // チャネル
    // 第1引数:受信した値
    // 第2引数:なし
    ch := make(chan int)
    go func() {ch<- 10}()
    for v := range(ch) {
        fmt.Println(v)
    }
}

Go游乐场

函数

Golang的函数

    • funcキーワードを使う

 

    • 2個まで返すことできる

 

    • 戻り値に名前を付けることができる

 

    関数終了時に呼び出す関数を登録するdefer文
// 引数・戻り値なし
func Fn1() {
    ...
}

// 引数あり
func Fn2(s string, b int) {
    ...
}

// 同じ型ならまとめられる
func Fn3(a, b int) {
    ...
}

// 可変長引数
func Fn4(s ...string) {
    ...
}

// 戻り値1個
func Fn5() int {
    return 1
}

// 戻り値2個
func Fn6() (int, int) {
    return 1, 2
}

// 名前付き関数
func Fn7() (v int) {
    ...
    return // 自動的に名前付きの変数が返される
    ...
    return 10 // 値をしてした場合, 指定した値が優先される
}

// defer文
// 関数はスタックに格納される(LIFO. 最後のdefer文が先に実行される)
// 関数終了時に実行するべき関数を登録しておく
func Fn8() {
    defer f(1)
    defer f(2)
    defer f(3)
}

形态宣言

声明Golang的类型

    • typedefに相当する

 

    • 基本型・複合型から新しい型を作成する

 

    • 元の型<->新しい型(代入可能・型変換可能)

 

    同じ基底型を持つ型同士(代入不可・型変換可能)
// type 新しい型 元の型
type myInt int
type myAry [10]int

结构体

Go语言的结构体

    • 継承はできない

 

    • 匿名フィールドに構造体を埋め込むことはできる

 

    各フィールドにタグ情報を埋め込める(xml,jsonのパースなどに使える)
package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int `key:"value"` // タグ情報
}

type Worker struct {
    Person // 匿名フィールド
    Work   string
}

func main() {
    var p1 Person
    p1.Name = "aiueo"
    p1.Age = 20
    p2 := Person{Name: "abcde", Age: 40}
    p3 := Worker{p2, "NEET"}
    fmt.Printf("%#v\n", p1)
    fmt.Printf("%#v\n", p2)
    fmt.Printf("%#v\n", p3)
}

Go Playground

指针

Golang的指针

    • 基本はC言語などと同様

 

    • &(アドレス参照演算子), *(間接参照演算子)を使う

 

    • 組み込み関数new(型)でメモリを確保する

 

    • 参照先のないポインタはnullではなくnil

GC(ガベージコレクション)で自動的にメモリは開放される
危険なポインタアクセスはできない(unsafeパッケージで扱える)

package main

import (
    "fmt"
)

func main() {
    v := 10
    p := new(int)
    *p = 100
    p1 := &v
    fmt.Println(*p)
    fmt.Println(*p1)
}

Go Playground

方法

使用Go编写的方法

    • typeで作成した型に関数(メソッド)を持たせることができる

 

    値レシーバ・ポインタレシーバ
package main

import (
    "fmt"
)

type Int int

type St struct {
    x int
}

func (v Int) add(n int) Int {
    return v + Int(n)
}

func (st *St) add(n int) {
    st.x += n
}

func main() {
    v1 := Int(10)
    v1 = v1.add(5)
    fmt.Println(v1)

    st := St{x:20}
    st.add(5)
    fmt.Println(st)
}

Go playground 在线编程调试器

界面

Go语言的接口

    • メソッドの集合

 

    • インターフェースを実装するにはすべてのメソッドを実装する

 

    • 構造体と同様に匿名フィールドにインターフェースを埋め込むことはできる

 

    • interface{}はすべての型の値が代入可能

 

    • interface型の「==」演算子は同じ型かつ同じ値のときのみtrueを返す

nilは型なしのnilとのみ一致する. 型がある場合はそれぞれのポインタ型のnilと一致する
元の型に戻すには型アサーションを使う(第1戻り値に変換した値, 第2戻り値に真偽値)
型switch文で型ごとの処理ができる

package main

import (
    "fmt"
)

type IAnimal interface {
    Name() string
    Cry() string
}

type Cat struct {
    name string
}

type Dog struct {
    name string
}

func (a Cat) Name() string {
    return a.name
}

func (a Cat) Cry() string {
    return "にゃん"
}

func (a Dog) Name() string {
    return a.name
}

func (a Dog) Cry() string {
    return "わん"
}

func main() {
    var a IAnimal
    a = Cat{"みけ"}
    fmt.Println(a.Name(), a.Cry())
    a = Dog{"ぽち"}
    fmt.Println(a.Name(), a.Cry())

    var n interface{} // なんでも代入できる
    n = 10
    n = "abc"
    fmt.Println(n)
}

Go语言的游乐场

package main

import (
    "fmt"
)

func main() {
    var i0 interface{} = 10
    var i1 interface{} = "a"
    var i2 interface{} = 10
    var v0 int = 20
    var v1 string = "b"
    fmt.Println(i0 == i1) // false(型だけの一致)
    fmt.Println(i0 == v0) // false(値だけの一致)
    fmt.Println(i1 == v1) // false(両方の不一致)
    fmt.Println(i0 == i2) // true(両方の一致)

    // 元の型に戻すことで代入可能
    v0, ok := i0.(int)
    if ok {
        fmt.Println("int変換成功", v0)
    }
    v1, ok = i1.(string)
    if ok {
        fmt.Println("string変換成功", v1)
    }

    switch v2 := i1.(type) {
    case int:
        fmt.Println("int", v2)
    case string:
        fmt.Println("string", v2)
    case float32, float64:
        fmt.Println("float", v2)
    }
}

Go 乐园

数组、切片、映射

Golang的数组和切片

    • []を型名の前に書く

 

    • 固定長を配列, 可変長をスライス

 

    • 配列は値型, スライスは参照型

 

    • 組み込み関数appendで拡張可能(容量が不足なら再割当てされる)

 

    • 組み込み関数makeでメモリ確保

 

    • 組み込み関数len, capで長さ, 容量を取得

 

    • 組み込み関数copyでスライスをコピー(コピー先の長さまでがコピー元の要素で上書きされる)

 

    • スライス式でスライスの一部を取り出し(0<=start<=end<=len, 新しいスライスの容量はlen-start)

 

    フルスライス式で取り出す容量を制限(0<=start<=end<=max<=len, 新しいスライスの容量はmax-start)

用Go语言的映射数据结构。

    • マップの型はmap[キーの型]要素の型

 

    • マップ[キー]で参照(第1戻り値が要素またはデフォルト値, 第2戻り値に真偽値)

 

    組み込み関数makeで要素数を指定した方が高速

数组(固定长度)

ary1 := [3]int{11, 12}       // 長さ指定([2]はデフォルト値)
ary2 := [...]int{21, 22, 23} // 長さ指定なし
ary3 := [3]int{0: 31, 2:32}  // インデックス指定
length := len(ary1)          // 長さの取得

切片(可变长)

slice1 []int           // nil
slice2 []int{11,12,13} // 長さ2
slice3 []int{21,22,23} // 長さ3

append(slice2, 14, 15, ...)  // 要素を追加(可変長引数)
append(slice1, slice3...)    // スライスを追加
slice4 := make([]int, 5)     // 長さ5(容量5)のスライスを確保(デフォルト値を設定)
slice5 := make([]int, 5, 10) // 長さ5・容量10のスライスを確保(デフォルト値を設定)
capacity := cap(slice5)      // 容量の取得
copy(slice5, slice2)         // slice5(長さ5)にslice2の要素が5つまで上書きコピー

slice6 := slice5[1:3]    // [1]-[3-1]
slice7 := slice5[2:]     // [2]-[len-1](最後)
slice8 := slice5[:2:     // [0](最初)-[2-1]
slice9 := slice5[:]      // [0](最初)-[len-1](最後)(コピー)
slice10 := slice5[1:3:5] // [1]-[3-1]を容量(5-1)

地图

map1 := map[string]int{"a":1, "b":2, "c":3}
k, v := map1["key"]
if v {
    fmt.Println(k)
} else {
    fmt.println("キーが存在しない")
}
map2 := make(map[string]int)     // 要素数の指定なし
map3 := make(map[string]int, 10) // 要素数の指定あり

错误

    • errorインターフェス

 

    panic

同时处理(协程)

    • 標準で並列処理ができる

goを関数に付けて呼び出すと別ルーチンで実行
通信用のチャネル型変数を使う
バッファなしチャネルは同期通信, バッファ付きチャネルは非同期通信(容量まで貯める)
組み込み関数closeでチャネルを閉じると受信以外できなくなる(クローズされている場合, 第1戻り値にデフォルト値, 第2戻り値に真偽値)
for rangeはチャネルがクローズされるまで繰り返す
select文を使うことで複数のチャネルを扱うとき送信待ち・受信待ちで他の操作ができなくなるのを防ぐ

chan int   // 送受信可能なチャネル型
chan<- int // 送信のみ可能なチャネル型
<-chan int // 受信のみ可能なチャネル型
make(chan int)    // バッファなしチャネル
make(chan int, 5) // バッファ付きチャネル
ch <- 10 // チャネル送信文
<-ch     // チャネル受信
close(ch)
n, t := <-ch
if t {
    fmt.Println(n)
}
// クローズするまで繰り返す
for n := range ch {
    fmt.Println(n, "を受信")
}
func Fn(ch1 chan<- int, ch2 <-chan string) {
    var s string
    select {
    case ch1 <- 10:
        fmt.Println("ch1送信")
    case s = <- ch2:
        fmt.Println("ch2受信") 

    // 受信も送信もできない場合
    default:
        fmt.Println("まだだよ")
    }
}
广告
将在 10 秒后关闭
bannerAds