LoginSignup
0
0

More than 3 years have passed since last update.

The Go Programming Language Specification メモ

Last updated at Posted at 2020-07-18

https://golang.org/ref/spec
版: Version of Jan 14, 2020

Source code representation

Implementation restriction: For compatibility with other tools, a compiler may disallow the NUL character (U+0000) in the source text.

Implementation restriction: For compatibility with other tools, a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF) if it is the first Unicode code point in the source text. A byte order mark may be disallowed anywhere else in the source.G

実装上の制約も書かれているのか。

Characters

In The Unicode Standard 8.0, Section 4.5 "General Category" defines a set of character categories. Go treats all characters in any of the Letter categories Lu, Ll, Lt, Lm, or Lo as Unicode letters, and those in the Number category Nd as Unicode digits.

Luなどの意味は以下。

 Lu = Letter, uppercase
 Ll = Letter, lowercase
 Lt = Letter, titlecase
 Lm = Letter, modifier
 Lo = Letter, other

Keywords

defaultってキーワードはどこで使うんだろ?

Integer literals

An optional prefix sets a non-decimal base: 0b or 0B for binary, 0, 0o, or 0O for octal, and 0x or 0X for hexadecimal.

prefixは大文字でも小文字でもよいのか。

For readability, an underscore character _ may appear after a base prefix or between successive digits;

アンダースコアで区切れるのね。

0xBadFace←16進数の例外が面白い。

Rune literals

A rune literal is expressed as one or more characters enclosed in single quotes, as in 'x' or '\n'.

ルーンリテラルはシングルクォーテーションで囲む。

little_u_value   = `\` "u" hex_digit hex_digit hex_digit hex_digit .
big_u_value      = `\` "U" hex_digit hex_digit hex_digit hex_digit
                           hex_digit hex_digit hex_digit hex_digit .

小文字'u'と大文字'U'とでは、その後に続けられる文字列が異なる。

String literals

`` : raw string
"" : interpreted string

The text between the quotes forms the value of the literal, with backslash escapes interpreted as they are in rune literals (except that \' is illegal and \" is legal), with the same restrictions.

interpreted literal でもUnicodeのコードポイントを指定できる。
例:"\u65e5本\U00008a9e"

Constants

in a short variable declaration such as i := 0 where there is no explicit type. The default type of an untyped constant is bool, rune, int, float64, complex128 or string respectively,

型を指定しなかったときのデフォルト型が書かれている。

Variables

If a variable has not yet been assigned a value, its value is the zero value for its type.

アサインされていない変数は、その型のゼロ値。

Method sets

The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

*TTを含むのはよく忘れる。

Numeric types

uint8       the set of all unsigned  8-bit integers (0 to 255)
uint16      the set of all unsigned 16-bit integers (0 to 65535)
uint32      the set of all unsigned 32-bit integers (0 to 4294967295)
uint64      the set of all unsigned 64-bit integers (0 to 18446744073709551615)

int8        the set of all signed  8-bit integers (-128 to 127)
int16       the set of all signed 16-bit integers (-32768 to 32767)
int32       the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64       the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)

このあたり、たまに確認したくなるが、そういうときはこの章を見るのがよい。

String types

A string value is a (possibly empty) sequence of bytes.

stringはバイトの並びであって、文字の並びではない。

Slice types

make([]int, 50, 100)
new([100]int)[0:50]

この2つは同じ意味。なるほど。

however with slices of slices (or arrays of slices), the inner lengths may vary dynamically. Moreover, the inner slices must be initialized individually.

2次元以上の場合、内側のスライスの長さは動的に変わる。

Struct types

If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

Tを埋め込むか、*Tを埋め込むかで、アクセスできるメソッドが上記のように変わる。

Function types

func(int, int, float64) (float64, *[]int)

この使いみちがわからなかったけど、関数型の引数を宣言するときに使うのかな。

Interface types

all types implement the empty interface:

なるほど。interface{}型に代入できるのは、すべての型は空インターフェースを実装しているからか。

If the key type is an interface type, these comparison operators must be defined for the dynamic key values; failure will cause a run-time panic.

キーにinterfaceを使った場合、その型が ==, != を定義していないとpanicになる。

Channel types

The <- operator associates with the leftmost chan possible:

chan<- chan int    // same as chan<- (chan int)
chan<- <-chan int  // same as chan<- (<-chan int)
<-chan <-chan int  // same as <-chan (<-chan int)
chan (<-chan int)

一見すると、何だこれって思いそうなのでメモ。

Type identity

B0 and B1 are different because they are new types created by distinct type definitions;

別々のtypeにより定義された型は、異なるとみなされる。

Label scopes

Labels are declared by labeled statements and are used in the "break", "continue", and "goto" statements.

gotoのみでなく、breakcontinueでもラベルは使える。

Exported identifiers

"export"という単語が使われている。パブリック/プライベート というよりは、エクスポートされてる/されてない という言い方のほうが正確なのかな。

Constant declarations

const a, b, c = 3, 4, "foo"

constantもこういう書き方ができるのか。

Iota

const (
    a = 1 << iota  // a == 1  (iota == 0)
    b = 1 << iota  // b == 2  (iota == 1)
    c = 3          // c == 3  (iota == 2, unused)
    d = 1 << iota  // d == 8  (iota == 3)
)

iotaが使われないときは、その値(ここでいうと2)はスキップされるのか。

const (
    bit0, mask0 = 1 << iota, 1<<iota - 1  // bit0 == 1, mask0 == 0  (iota == 0)
    bit1, mask1                           // bit1 == 2, mask1 == 1  (iota == 1)
    _, _                                  //                        (iota == 2, unused)
    bit3, mask3                           // bit3 == 8, mask3 == 7  (iota == 3)
)

複数利用もできるのか。

Type declarations

2種類ある
- alias declarations
- type definitions

A defined type may have methods associated with it. It does not inherit any methods bound to the given type, but the method set of an interface type or of elements of a composite type remains unchanged:

type definitions ではメソッドは継承されないが、以下は継承される
- インターフェースのメソッド
- 埋め込み型

Short variable declarations

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new.

err変数の再定義を雰囲気で書いていたとこが正直あったけどスッキリ。

a, err := Func()
b, err := Func() // bが新たな変数だから、errの再定義はOK
_, err := Func() // 新たな変数がないから、errの再定義はNG

Function declarations

A function declaration may omit the body. Such a declaration provides the signature for a function implemented outside Go, such as an assembly routine.

(見たことないけど、)関数定義はボディを省略できる。その場合は外部(アセンブリなど)で定義されているとのこと。

Method declarations

A method is a function with a receiver.

メソッドの定義が簡潔に書かれている。

Its type must be a defined type T or a pointer to a defined type T.

レシーバーは defined type である必要があるから、type alias にメソッドはバインドできないことがわかる。

The type of a method is the type of a function with the receiver as first argument. For instance, the method Scale has type

func(p *Point, factor float64)

レシーバーがnilであってもメソッド呼び出しできるのは、この仕様によるため。
JavaやC#の感覚だと驚くポイント。

Composite literals

p1 := &[]int{}    // p1 points to an initialized, empty slice with value []int{} and length 0
p2 := new([]int)  // p2 points to an uninitialized slice with value nil and length 0

スライスやマップで、上の2つは生成された結果が異なる。
基本、前者で書くことしかなさそうだけど、一応メモ。

// vowels[ch] is true if ch is a vowel
vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}

// the array [10]float32{-1, 0, 0, 0, -0.1, -0.1, 0, 0, 0, -1}
filter := [10]float32{-1, 4: -0.1, -0.1, 9: -1}

arrayに対して<index>:<value>と書ける。

Selectors

The identifier f is called the (field or method) selector;

「セレクタ」と呼ぶ。

As an exception, if the type of x is a defined pointer type and (*x).f is a valid selector expression denoting a field (but not a method), x.f is shorthand for (*x).f.

この仕様により、ポインタに対して直接.でつなげてフィールドが取れる。

For example, given the declarations:

type T0 struct {
    x int
}

func (*T0) M0()

type T1 struct {
    y int
}

func (T1) M1()

type T2 struct {
    z int
    T1
    *T0
}

func (*T2) M2()

type Q *T2

var t T2     // with t.T0 != nil
var p *T2    // with p != nil and (*p).T0 != nil
var q Q = p

t.z          // t.z
t.y          // t.T1.y
t.x          // (*t.T0).x

p.z          // (*p).z
p.y          // (*p).T1.y
p.x          // (*(*p).T0).x

q.x          // (*(*q).T0).x        (*q).x is a valid field selector

p.M0()       // ((*p).T0).M0()      M0 expects *T0 receiver
p.M1()       // ((*p).T1).M1()      M1 expects T1 receiver
p.M2()       // p.M2()              M2 expects *T2 receiver
t.M2()       // (&t).M2()           M2 expects *T2 receiver, see section on Calls

思うようにセレクタで呼びせないときは、この例で確認するのが良さそう。

Function values derived from methods are called with function call syntax; the receiver is provided as the first argument to the call. That is, given f := T.Mv, f is invoked as f(t, 7) not t.f(7).

メソッドを関数として代入した場合、レシーバーを第一引数とした関数として呼び出される。
(つまり、レシーバーのnilチェックがメソッドの内に書かれていたとして、問題なく動く。

Method values

The expression x is evaluated and saved during the evaluation of the method value;

メソッド値として代入したあとに、その構造体の状態を更新した場合、代入した側に影響はあるのだろうか?
要確認。

Full slice expressions

a[low : high : max]

こういう書き方で、スライスに切り出したときのキャパシティをmaxを使って指定できる。
max - lowがキャパシティになる。

Comparison operators

Pointers to distinct zero-size variables may or may not be equal.

↓のようなコード書いてみたけど、2つのポインタが同一になるケースは再現できず。

package main

import (
    "fmt"
)

func main() {
    var eq, ne int
    for i := 0; i < 1000000; i++ {
        var s1, s2 struct{}
        if &s1 == &s2 {
            eq++
        } else {
            ne++
        }
    }
    fmt.Printf("eq: %d, ne: %d\n", eq, ne)
}

Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

構造体の比較についてはここに書かれている。
フィールドが可能で、かつ、フィールドが同じなら同一。

Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil.

スライス、マップ、関数値がnilと比較できるのは特別ケース。

Conversions

If the type starts with the operator * or <-, or if the type starts with the keyword func and has no result list, it must be parenthesized when necessary to avoid ambiguity:

*Point(p)        // same as *(Point(p))
(*Point)(p)      // p is converted to *Point

このあたり、雰囲気で型変換していた気がする。

Conversions to and from a string type

Values outside the range of valid Unicode code points are converted to "\uFFFD".

Unicodeのコードポイント範囲外の場合は\uFFFDに変換される。\uFFFDになったら意図しない変換になっていないかをチェック。

Constant expressions

const Θ float64 = 3/2      // Θ == 1.0   (type float64, 3/2 is integer division)
const Π float64 = 3/2.     // Π == 1.5   (type float64, 3/2. is float division)

前者で書いて「float64にしたつもりが!」って嵌りそうなのでメモ。

Constant expressions are always evaluated exactly; intermediate values and the constants themselves may require precision significantly larger than supported by any predeclared type in the language. The following are legal declarations:

const Huge = 1 << 100         // Huge == 1267650600228229401496703205376  (untyped integer constant)

型指定してなければOKってこと?

Switch statements

There are two forms: expression switches and type switches.

日本語だと、「式スイッチ」、「型スイッチ」という呼び方かな。

For statements with range clause

with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.

len(x)が定数であるならrange句は評価されないので、例えば以下のようなコードが動いていまう。
(これに遭遇したらハマりそうなのでメモ)

package main

import (
    "fmt"
)

func main() {
    var testdata *struct {
        a *[7]int
    }
    // fmt.Println(testdata.a) // <- panic: runtime error: invalid memory address or nil pointer dereference
    for i, _ := range testdata.a {
        // testdata.a is never evaluated; len(testdata.a) is constant
        // i ranges from 0 to 6
        fmt.Println(i)
    }
}

Defer statements

For instance, if the deferred function is a function literal and the surrounding function has named result parameters that are in scope within the literal, the deferred function may access and modify the result parameters before they are returned.

named result parametersの場合は、以下のようにdeferの中で戻り値を変更可能。

// f returns 42
func f() (result int) {
    defer func() {
        // result is accessed after it was set to 6 by the return statement
        result *= 7
    }()
    return 6
}

Length and capacity

The expressions len(s) and cap(s) are constants if the type of s is an array or pointer to an array

この言語仕様を知ってないと、ポインタはnilなのにlen(a)で10が返るの、「なんで?」ってなりそう。

package main

import (
    "fmt"
)

func main() {
    var a *[10]int
    fmt.Println(a) // -> nil
    fmt.Println(len(a)) // -> 10
}

Appending to and copying slices

var b []byte
b = append(b, "bar"...)            // append string contents      b == []byte{'b', 'a', 'r' }

stringに...をつけるとbyteのスライスになるのか。

The number of elements copied is the minimum of len(src) and len(dst).

単純に全部コピーされるわけじゃない。(src, destの長さが小さいぶんだけ)

Import declarations

If an explicit period (.) appears instead of a name, all the package's exported identifiers declared in that package's package block will be declared in the importing source file's file block and must be accessed without a qualifier.

名前の代わりに.をつかうと、識別子なしにエクスポートされたものが呼べる。

import . "lib/math"         Sin

To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name:

pqなどをインポートは初期化だけが目的だから_でインポートしているということ。

Package initialization

However, initialization always sequences the init functions: it will not invoke the next one until the previous one has returned.

init関数は平行に実行されることはない。(順次実行される)

Program execution

It does not wait for other (non-main) goroutines to complete.

main関数は、その他のゴルーチンの終了は待たずに終了する。

Run-time panics

Execution errors such as attempting to index an array out of bounds trigger a run-time panic equivalent to a call of the built-in function panic with a value of the implementation-defined interface type runtime.Error.

runtime.Errorインターフェースがあり、実装系で定義されたそのインターフェースを満たす値が、panicでは使われる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0