Go语言的笔记

因为变得混乱了,所以我在工作期间写了一篇关于golang的备忘录。

数据结构

值和处理

名前役割変数単数の値の型の入れ物関数単数の処理の型の入れ物構造体複数の値の型の入れ物インターフェイス複数の処理の型の入れ物

复合体

名前役割ゼロ値配列固定長の配列各要素のゼロ値構造体固定長の連想配列各要素のゼロ値スライス可変長の配列nilマップ可変長の連想配列nil

可变长度的复合体的注意事项。

// スライスやマップは内部にlen、capの情報を独自に保持するため、
// nil(参照先のオブジェクトなし)でlen関数を行っても、実体を見ずに0が返ってくる感じ
// 変だと思っていたが、スライスなどのフィールドの値がゼロ化されただけの正常な感じと解釈している
v := map[string]string{}
fmt.Println(len(v), v==nil) // 0, false
var v2 map[string]string
fmt.Println(len(v2), v2==nil) // 0, true

切片的结构

    • arrayへの参照

 

    • そのarrayのlen

 

    そのarrayのcap

地图的结构 de

在中国本土游戏市场中,对电子竞技的兴趣与日俱增。

界面结构

把以下内容用中文进行本地化改写,只需要一个选项:
TODO

字面意义

字面上的列表

リテラルの種別特徴基本リテラル初期型を持ち、柔軟に代入可能複合リテラル構造体、配列、スライス、マップのどれかの値を作成する関数リテラルクロージャーのこと型リテラル構造体、配列、ポインター、関数、インターフェイス、スライス、マップ、チャンネルの型のこと

基本字面意义

リテラルの種別特徴数値リテラル数値リテラル(10, 8, 16進数)浮動小数点リテラル浮動小数点虚数リテラル虚数ルーンリテラルユニコードのコードポイントの数値文字列リテラル(エスケープシーケンスの)解釈有りと無し版がある
12 // リテラルは型を持たない(そのかわり初期型がある)ため、
   // 12の場合は、intにもfloat64にも代入可能
var a int = 12
var g float64 = 12

复合字面量

// 複合リテラルは構造体、配列、スライス、マップのどれかの値を作る

// また、構造体、配列、スライス、マップはそのままリテラルにできる
// 構造体リテラル、配列リテラル、スライスリテラル、マップリテラルと呼ばれる
struct{}{}, [...]int{}{}, []int{}{}, map[string]string{}
// それらの省略記法
[...][]int{[]int{1, 2}, []int{2, 3}}}
[...][]int{{1, 2}, {2, 3}}} // 省略記法


// また、複合リテラルの波括弧は配列などと同じ複数のインデックス式を意味するので
v := struct{
   name string
   age int
} {
   name: "hoge", // 構造体の複合リテラルにはカンマが必要
   age: 12,
}

// 複合リテラルの例
type MyInt int // 名前付き型(基底型は事前宣言済み型)
v := []MyInt{12} // 名前付き型MyIntの複合リテラル(スライスの値)
v2 := map[interface{}]interface{}{"age":12} // インターフェイスの型リテラルを持つ複合リテラル(マップの値)

// 複合リテラルはまた、アドレス演算子をつけることで、
// リテラル値と初期化されたユニークな変数へのポインタを生成する
v := &struct{}{}

// 関数型は間違えやすいので注意
type F func() // 関数リテラルを元に、名前付きの型(基底型は関数型)の宣言
// F{} // Error: 名前付きの型から関数リテラルは無理(これは複合リテラルと評価されるため)
[]F{func(){}} // 複合リテラルの値(構造体、配列、スライス、マップのどれか)として使用しなければならない

函数字面量 (闭包)

// 関数リテラルは複合リテラルではない点に注意
// 複合リテラルは波括弧に複数要素を意味し、インデックス式を使うが、
// 関数リテラルの波括弧はスコープを意味する
func()int{return 1} // クロージャーだからスコープのセマンティクスの波括弧を使ったリテラルが許される

字面值

// 構造体、配列、ポインター、関数、インターフェイス、スライス、マップ、チャンネルの型のこと
interface{} // Any型など
struct{}
// ※型リテラルと複合リテラルの違いは以下のような感じ
struct{} // 型リテラル
struct{}{} // 複合リテラル

样式

预先声明类型

// プリミティブな事前宣言済み型は以下
bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr

有名字的类型

// 名前付き型は次の2種類
// ①事前宣言済み型か、
// ②typeで宣言された型(型リテラルに名前をつけるか、既存型にエイリアスをつけられる)
type 新しい型名 型リテラル or 既存の型

匿名类型

// 無名型は名前付き型以外の型、
// 要はtype宣言されていない、型リテラルのこと
[]string
*int

综合类型 (composite type)

// 以下が複合型
Composite types array, struct, pointer, 
function, interface, slice, map, and channel types 
// つまり、type宣言されていない複合型=無名型であり、
// 構造体、配列、スライス、マップか、型リテラルを使ってtype宣言した名前付き型を
// 波括弧とインデックス式と共にインスタンス化したものが、複合リテラルである(ややこしい)

基底型 (underlying type) 的中文释义是什么?

// 全ての型Tには基底型がある。
// Tがboolean, numeric, or string types, or a type literalの場合はTの基底型はそれ自身
// 型宣言(type)で作成した型は元の型の基底型を引き継ぐ
type T1 string //T1の基礎型はstring
type T2 T1     //T2の基礎型はT1の基礎型のstring
type T3 []T1   //T3の基礎型は[]T1(なぜなら[]T1は型リテラルのため)
type T4 T3     //T4の基礎型はT3の基礎型の(なぜなら[]T1は型リテラルのため)

动态类型和静态类型

var n int = 42         // nの静的型はint
var s string = "hello" // sの静的型はstring
var v interface{}      // vの静的型はinterface{}
v = n                  // vの静的な型はinterface{}、動的型はint

类型转换(类型函数)、类型断言(匿名类型方法)

// キャスト
type (MyInt1 int, MyInt2 int) 
var m1 MyInt1 = 10; var m2 MyInt2
m2 = MyInt2(m1) // 基底型が一致しているので変換可能
// アサーション
v = x.(T); v, ok = x.(T)
switch t := x.(type) { // switch文ではtypeキーワードを使える
  case T:
}

初始化、初始化器、初始类型和初始值(零值)

// newやmakeは初期化子
var hoge T // 明確な初期化がないので、ゼロ値が入る
hoge2 := new(T) // Tの参照型(ポインタ型)
hoge3 := make([]T, length, capacity) // Tの値型

指针

指针类型的类型文字表达

*int // * と 型リテラル

地址运算符

// &"" // 単一リテラルにはメモリが割り当てられていないので無理
v := &struct{}{} // 複合リテラルはOK

引用(->)

var n int = 1
var p *int = &n

fmt.Println(n)  // 1
fmt.Println(&n) // 0x10328000
fmt.Println(p)  // 0x10328000
fmt.Println(*p) // 1  デリファレンス

变量

A variable is a storage location for holding a value. 
The set of permissible values is determined by the variable's type.

变量声明有四种类型

var hoge T // 型のゼロ値で初期化される
var hoge T = 12 // hogeの型はTで12がその初期値
var hoge = 12 // 型なし変数宣言、リテラルの型または初期型がhogeに使用される
hoge := 12 // ローカル変数の宣言

所有权和操作权 hé

var hoge string
hoge = "age" // hogeはインスタンスの所有権と操作権をもってる
var hoge2 string = "age"
hoge3 := "age" 

本地变量,全局变量

var glo = 12 // トップレベルスコープでの宣言はグローバル変数となる
func main(){
    hoge := 12 // ち◯こ演算子はローカル変数のみ使える
}

常数

内建常量

true, false, iota

制作方式

// 定数に使用できるのは基礎型のみ
const hoge int = 12 // 型ありの定数 
const hoge2 = 12 // 型無の定数、なのでリテラルと同じように扱える
// var hoge3 float = hoge // エラー
var hoge3 float = hoge2 // OK

借助列挙体

const (
  c1 int = iota // 0
  c2 // c2==1, int型
  _ // iotoと解釈される

  c3 // c3==3, int型
)

范围

范围的种类

universe block
package block
file block
"if", "for", and "switch" statement
Each clause in a "switch" or "select" statement

作用域符号

{
   // here is local scope
}

本地作用域,全局作用域

var global int
func hoge() {var local int}

词法作用域 fǔ)

TODO

函数

内置函数

append cap close complex copy delete imag len
make new panic print println real recover

参数(Parameter)和参数(Argument)

func hoge(aaa string) {} // aaaはhoge関数の仮引数
aaa := "age"
hoge(aaa) // aaaはhoge関数の実引数

有名的返回值和空白,类型省略。

func hoge(age int, _ string, name, addr string) {}

可变参数(剩余参数)

// 可変引数は最後の引数で指定できる
func hoge(age int, opt ...string) {}
// 実引数を入れる方法は2つ
hoge(12, "opt1", "opt2") // string型を可変で実引数にわり当てられる
hoge(12, []string{"opt1", "opt2"}...) // slice型を予め実引数にすることも可能

返回值

// 戻り値を返す方法は2つ、
func hoge() string {return ""}
func hoge() (string, error) {return "", nil } // 複数戻り値がある場合はタプルで指定する
func hoge() (name string) {return} // nameはゼロ値で初期化されるので、それが返る
func hoge() (name string) { name="aho"; return } // 名前付き戻り値バージョン、"aho"が変える
func hoge() (name string) { return "teko"} // return文に値があった場合はそちらが優先される

函数式

type F func() // 関数の型リテラルを名前付きの型として定義
s := []F{func(){}} // ここで []F{F{}}とはできない

函数字面量(闭包)

f := func() {}

立即执行函数(闭包)

func(i int) int { return i }(0)

替代

将其代入并留空

v, _ = "hoge", "hoge"
_ = v // unused variable回避

元组?

f := func()(v, v2 string){} // 複数返せる関数を作れる
v, v2 = f() // 複数代入できる
## ゼロ値(zero value)
```go
// 変数宣言またはnew関数のコールか、複合リテラルまたはmake関数のコールか、
// 明確じゃない初期化が提供された時
false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps

结构体

结构体的类型字面量

stuct{}

结构体字面量

//変数(フィールド)ごとに値を格納するメモリを持つ値型のデータ構造
// 型リテラル表記のときの波括弧はカンマで区切られた式を持つ複数の要素を示しており、
// 構造体リテラルでもカンマが必要な理由は、それを統一するため?
stuct{}{}

领域

type T {
  age int
}
v := &T{age: 12}
v.age // 12

匿名字段

// 匿名フィールドに設定できるのは、名前付き型もしくはそのポインタ型のみ(型リテラルだめ)
// また、匿名といってもその名前付き型の名前が暗黙的に型名になる
// 匿名フィールド内のフィールドとメソッドは、その構造体直管のフィールドとメソッドへ昇格される
type S []string
type T struct {
  string
  // []string // NG
  S // OK
}

标签

// タグはリフレクションで解析可能

排列

数组的类型字面量

[2]int
[10]int
[...]int

数组字面量

[2]int{1,2}
[10]int{1,2}
[...]int{1,2,3}

对数组进行操作

a := make([2]int, 2, 10) // 2=length, 10=capacity, 各要素はゼロ化されている
a[0] = 1
fmt.Println(a[0])
b := a // arrayは値型なので=でコピー可能

切片(可变长数组)

切片类型的文字表示

[]string
[]interface{}
[]int

切片文字

[]string{"1","2"}
[]interface{}{1,""}
[]int{1,2,3}

切片操作 (qiè ​ zuò)

v := make([]int, 2, 10) // 2=length, 10=capacity, 各要素はゼロ化されている
len(v) // 長さ
cap(v) // 容量
// 結合
c = append(a, b...) // cはaとbが結合されたもの
// append
// ※appendは元のスライスの容量を超えた場合、新しいスライスを作成する
a = append(a, b, c) // b and c are element 
// copy
b = make([]T, len(a))
copy(b, a) // sliceは参照型なので=ではコピーはできない
// delete
a = append(a[:i], a[i+1:]...)
// cut
a = append(a[:i], a[j:]...)
// pop
x, a = a[len(a)-1], a[:len(a)-1]
// push
a = append(a, x)
// unshift
a = append([]T{x}, a...)
// shift
x, a := a[0], a[1:]
// 空にする
a := [...]int{1, 2, 3, 4, 5}
a = nil
fmt.Println(a) // => "[]"

切片式

// スライス式はつぎの書式 [low:hight:max]
s[0:1] // 0は開始値, 1は終了値
s[0:] // 終了値はlen(slice)と同じ値になる
s[:] // 開始値は0, 終了値はlen(slice)と同じ値になる
// ※(フル)スライス式で取得したスライスは取り出し元と同じメモリを使用されるので注意
s := []int{1, 2, 3}
s2 := s[:] 
s2[0] = 12 // 12, 2, 3 となっている

全切片式

// スライス式は暗黙的にmax=len(slice)となっている。
// そのため、明示的にフルスライス式でmaxを指定しないと、
// 切り出したものより大きな値にアクセスできてしまう
a := make([]int, 10) // 長さ10の配列
s := a[0:5]          // 長さ5のスライスsを切り出す
t := s[0:10]         // sからsより長いスライスtを切り出す

线条

len("あ")
"あ"[0:4] // あ(3バイト)

地图 (dì tú)

地图类型文字

map[string]int

地图直接

map[string]int{"key": 1, "key2": 2}

地图操作

m := make(map[string]int) // map作成
v := map["key"] // キーの要素または、存在しないキーの場合はゼロ値が返る
v, hasKey := map["key"] // 上記の方法だと要素が存在するか分からないので
                        // 第二引数を見る(hasKeyはbool型)
// キーの削除
delete(m, "key") // mからkeyの要素を削除する

像是班级的感觉

领域

type T struct {f string}

方法

type T struct {f string}
func (*T) M() {}

访问权限

type T struct{
   pri int // プライベート
   Pub int // パブリック
}

配件

func (*T) GetHoge(hoge string) string{return T.hoge} // ゲッター
func (*T) SetHoge(hoge string) {T.hoge = hoge} // セッター

构造函数和析构函数

type T struct{ hoge string }
func NewT(hoge string) *T{ 
  return &T{ hoge: hoge }  // ここはイニシャライザ
}

你问的是“インデクサ”吗?

type P map[string]interface{}
func (p *P) hello() { fmt.Println((*p)["age"]) }

p := &P{}
(*p)["age"] = "hello"
p.hello()

接口

type H interface {
    hello()
}
type T struct{ H }
func (r *T) hello()  { fmt.Println("hello desu") }
var v H = &T{}
v.hello()

扩展是什么?

type T struct{ f string }
func (r *T) hello() {}
type T2 struct{ T }
func (r *T2) hello2() {}

v := &T2{}
v.hello()
v.hello2()

聚合(具有)

type T struct{ f string }
func (r *T) hello() {}
type T2 struct{ t: T }
func (r *T2) hello2() {}

v := &T2{t:&T{}}
v.t.hello()
v.hello2()

委托(将接口嵌入到结构体中)

type Superable interface{ a(); b() }
type Super {}
func (*Super) a() {}
func (*Super) b() {}

type Subable interface{ a(); b(); c() }
type Sub { Superable }
func (*Sub) c() {}

// main
var sub Subable := &Sub{Superable: &Super{}}
sub.a(); sub.b(); // subはaとbの処理をsuperに委譲している
sub.c() 

向上转型·向下转型

“Please provide more context or specify the text you need paraphrased in Chinese.”

覆写?

type T struct{ f string}
func (r *T) hello() { fmt.Println("hello") }
type T2 struct{ T }
func (r *T2) hello() { fmt.Println("hello from T2") }

v := &T2{}
v.T.hello() // もとの
v.hello() // オーバーライド済み?

超載?

type T struct{ f string}
func (r *T) hello() { fmt.Println("hello") }
type T9 struct{ T}
func (r *T9) hello(args ...interface{}) { // ここで型スイッチを書いて、r.T.hello()を呼び出す感じ? }

v9 := &T9{}
v9.hello("age", false) // オーバーロードっぽく

课堂方法?

type T struct{}
func (*T) hello() {}
(*T).hello(nil) // メソッド式では第0仮引数がそのレシーバーになる

界面

Any类型

type Any interface{}
var v Any = "なんでも"

鸭子打字

// 明示的に実装する必要なし
type I interface{ sound() }
type T struct{}
func (*T) sound() {}
var v I = &T{}
v.sound()

泛型?

// TODO 
v interface{} = 12
vi, ok := v.(int)

类型断言

v interface{} = 12
vi, ok := v.(int)

型切换

var v interface{} = 12
switch v.(type) {             // vの静的型がインターフェイス型だからできる
  case int:                   // 値ではなく、型で分岐する
   fmt.Println("基底型はint")
  case nil:                   // nil(値)が使える(jsでいうundefined)
   fmt.Println("基底型は不明") // これは値が無くて型が分からないときのため
}

方法

接收器和声明方式 qì hé

type T
func (r *T) Method() {}

调用方法的方式

type T
func (*T) Method() {}
v := &T{}
v.Method() // メソッドのインスタンスを含めて使いたい時
var v2 *T 
v2.Method() // メソッドを単純に使いたいときだけ

方法表达式

func (p T) M(arg1 string) {} // こんな形で書くが、
func T.M(p T, arg1 string) {} // 内部的にはこんな形になっている

T.M(T{}, "hoge) // なので左の用に呼び出せる

调用方法式

type T struct{ Name string }
func (r T) M1() {}
func (*r T) M2() {}

p := P{Name: "Hoge"}; p2 := &P{Name: "Hoge"}
// 以下は等価
p.M1(); P.M1(p) // メソッド式
p2.M1();(*P).M2(p2) // メソッド式 ( p2.M1() は暗黙的に型変換が行われている)

指针类型接收器和值类型接收器

// レシーバーは第0引数であり、もし値型でレシーバーを書いた場合は、そのレシーバーの値がメソッドにコピーされるので、そのレシーバー(第0引数)を更新することができない
// つまり、値型レシーバの値はメソッド内で書き換えても元のレシーバの値にはまったく影響がない
type T struct{ name string }
func (r T) getName() { return r.Name }
func (r T) setName(name string) { r.name = name}

v := T{name: "Taro"} // vの値はsetNameメソッドに値型としてコピーされるので、フィールドを書き換えても影響ない
T.setName(v, "Hoge")
v.setName("Hoge")
fmt.Println(v.getName()) // Taro

错误处理

延遲構文

// deferは順次にスタックのように積み上げられ、関数実行後に実行される。
// 名前付き戻り値と引数はdeferでも参照可能
defer func(){}() // 関数終了後2番目に実行される
defer func(){}() // 関数終了後1番目に実行される

包装

访问权限

var pri int // プライベート
var Pub() {} // パブリック

包裹名称规则

package main // mainを除くパッケージはフォルダ名と同一になる

顶级作用域的关键字

// パッケージのトップレベルは以下の5つ(単数の値、単数の処理 or タイプ)
type, func, method, var, const

包的初始化函数

func init() {}
func init() {} // init関数は同じパッケージに複数かける

内部包装

// internalが含まれる階層配下はインターナルパッケージ
package internal

导入路径

パスの指定方法意味相対パス同一パッケージ絶対パスなしその他のパスgolangのパッケージ

导入方法 rù fǎ)

パスの前方の識別子意味なし普通のインポートエイリアスパッケージ名のエイリアスドット(.)パッケージ名省略してそのパッケージの中のものを使用可能ブランク(_)インポートのみ(そのパッケージの中のinit関数は実行される)

不需要编译的目标名称

名前効果ドット(.)かブランク(_)で始まるファイルコンパイル対象外testdataフォルダテストデータ格納用フォルダ。コンパイル対象外

句法构造

按照次序构建

var hoge = 12
hoge = 14
fmt.Println(hoge) 

分叉结构

// if文
if v := true; v == true { // ち◯こ演算子でローカル変数の宣言も可能
  fmt.Println("true")
}
// select文
select hoge { // fallthroughで抜けれるかわりbreakはなし
  case 1:
     fmt.Println("hoge = 1")
  default
}
// switch文

多次构造

// while文
i := 0
for ; i < 10; { i++ }
// while true {}
for {}
// for文 
for i:=0;i<10;i++ {}  // continue, breakなど使用可能
// 拡張for文(foreach ループ)
for i, v := range hoge {}

前往モア

goto jump
fmt.Println("なぜ表示されない?")
jump: // ラベル

并行处理

携程(例程)

go func() {}()

共有变量

TODO

频道

TODO

其他

将日常例行事务外包化的方法

    パッケージ(モジュール、ライブラリ、フレームワークとか?)

主程序的共享方式

    • 構造型プログラミングっぽく(メインルーチンで型ごとの条件分岐を書く)

 

    • インターフェイス

 

    • 構造体の埋め込み

 

    ジェネリクスっぽく

子程序的共享方式

    • 関数

 

    • プロシージャ

 

    • メソッド

 

    クロージャー

常规解耦化

    • 仮引数・実引数

 

    ローカル変数(グローバル変数を使わない)

例: 路线隐藏化(封装)

    • アクセッサー

 

    • インターナルパッケージ

 

    • スコープを切る

 

    • アクセス権限

 

    • フィールド

 

    クロージャー

文献引用

https://golang.org/ref/spec – Golang规范
https://golang.org/doc/effective_go.html – Golang的编写有效Go代码
https://github.com/golang/go/wiki/SliceTricks – Golang切片技巧维基页面

以下中文翻译如下链接:

http://e-words.jp/w/ルーチン.html
http://www2.cc.niigata-u.ac.jp/~takeuchi/tbasic/Intro2Basic/Structure.html#control
http://qiita.com/atsaki/items/3554f5a0609c59a3e10d
https://ja.wikipedia.org/wiki/委譲
http://qiita.com/atsaki/items/3554f5a0609c59a3e10d#型とインターフェース
http://stackoverflow.com/questions/32983546/named-and-unnamed-types

https://skatsuta.github.io/2015/12/29/value-receiver-pointer-receiver/
http://golang.jp/tag/go言語仕様/page/3
http://qiita.com/jca02266/items/56a4fb7b07b692a6bf34
http://qiita.com/ruiu/items/f3516b705e6a7f2efb05
https://blog.golang.org/go-slices-usage-and-internals

广告
将在 10 秒后关闭
bannerAds