2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

go の知らなかった仕様

Last updated at Posted at 2022-07-18

これは何?

まあタイトルのとおり。
知らなかった文法・仕様・書き方がいくつかあったのでメモ。

型の別名定義

下記の、 newNameOfString

go1.18
// = があると、C の typedef 相当。別名。
type newNameOfString = string

// = が無いと、同じ内容の別の型。
type somethingLikeString string

func (s *newNameOfString) fuga() {} //invalid receiver type *string (basic or unnamed type)

func (s *somethingLikeString) fuga() {}

func piyoFunc() {
	s := "hoge"
	var nns newNameOfString = s
	var sls somethingLikeString = s // cannot use s (variable of type string) as somethingLikeString value
	// 以下略
}

こんな機能あったっけ。

[Go] Defined type(Named type)とType aliasを使い分ける によると、go 1.9 かららしい。私が初めて触った辺りかな。

= 無しだと新しい型なのでメソッド生やしたりできる。= 有りだと単に別名なので元の型と混ぜて使える。

ビルドタグ

従来

古いgo
// +build ignore

だったんだけど、いつの間にか

go1.18とか
//go:build ignore

と書くように変わった模様。
vscode で書いていたら、format on save で急に修正されてびっくりした。

私としてはコメントであることをやめるべきだと思ってるんだけど、そこは変えないのか、と思った。

メンバを持っている匿名構造体

こういうやつ。

go1.18
func anostructReceiver(ano struct{ a int }) {
}

func anostructSender() {
	anostructReceiver(struct{ a int }{a: 100})
}

これはまあ、メンバー無しではよく使うから言われてみればああそうかという感じだけど、使えるかもしれないと思ったことがなかった。

struct{} 以外の匿名構造体を使いたいと思う場面に遭遇していないから気づいていなくても仕方ない。

そう思うと。
interface{}any という名前がついているように、struct{} にもなんか名前つけたらいいんじゃないかなと思う。

Defined Type の挙動

time.Duration などで慣れている通り、defined type に対しても演算子による演算は普通にできる。

しかし構造体のメソッドは

go1.18
type EmbeddedType struct{}

func (*EmbeddedType) Embedded() {}

type OriginalStruct struct {
	EmbeddedType
	hoge int
}
type AnotherStruct OriginalStruct

func (*OriginalStruct) Foo() {}

func structUser(o *OriginalStruct, a *AnotherStruct) {
	o.Foo()
	o.Embedded()
	someFunc(o.hoge)
	a.Foo() // a.Foo undefined (type *AnotherStruct has no field or method Foo)
	a.Embedded() // これは OK
	someFunc(a.hoge) // これも OK
}

Defined type からは呼べない。
元の型に埋め込まれている型へのメソッドとかは OK。

じゃあ interface はと思うと

go1.18
type OriginalIF interface{ Bar() }
type AnotherIF OriginalIF

func ifUser(o OriginalIF, a AnotherIF) {
	o.Bar()
	a.Bar() // これは OK
}

と defined type でもメソッドが使える。

評価順序

C / C++ なんかだと

c_or_c++
foo(bar(),baz());

barbaz が呼ばれる順序が曖昧で最適化オプションを変えると順序が変わったりする。

go の場合どうなのか知らなかったんだけど The Go Programming Language Specification - Order of evaluation を見ると

go
a := 1
f := func() int { a++; return a }
x := []int{a, f()}            // x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified

などとなっていて、不定らしい。

気をつけないとね。

goto

あるらしい

私は書かないと思う。

type(...)

こう書いてもいいらしい。

go1.18
type (
	OriginalStruct struct {
		EmbeddedType
		hoge int
	}
	AnotherStruct OriginalStruct
)

見たこと無いから知らなかった。

これも書かないかな。他の人が書いていても驚かないようにしよう。

まとめ

キャッチアップちゃんとしなきゃね、と思った。

2
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?