最近のGoのイベントでDevquiz枠を設けられるケースが出てきたけど、答え合わせが会場で行われたりするしまとまってるところがないので作った。(あと、間違えた人が気づかないんじゃないか説)
原則
- 現在募集中のイベントのDevquizの答えは公開しません。
- コメントにも書かないでね
- 問題は忘れそうなので、書いておくかも。
- イベントに参加した or 存在に気づいたら随時、更新する(予定!)。
- この記事に書いた答えで、間違ってたら訂正は受け付けます。(別解Welcome!!)
過去問
Go Conference 2018 Spring
問題
次のプログラムを実行しようとした場合に何がおきますか?
package main
import (
"fmt"
)
type Hoge struct{}
func (h *Hoge) M() {
fmt.Println(h)
}
func main() {
var h *Hoge
h.M()
}
選択肢
1. コンパイルエラー
2. パニックが発生
3. <nil>と表示される
4. 何も表示されない
解答
3. <nil>と表示される
何も格納していないHogeをポインタにしているのでnilになります。
それを表示しているので<nil>
が表示されます。
golang.tokyo #14
問題
次の関数f
を実行した場合に何がおきますか?
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
}
}()
done := make(chan struct{})
go func() {
panic("hoge")
close(done)
}()
<-done
fmt.Println("fuga")
}
選択肢
1. コンパイルエラー
2. パニックが発生
3. <nil>と表示される
4. 何も表示されない
解答
2. パニックが発生
https://play.golang.org/p/bM84kHgqg2i
f()
と別のgoroutineでPanicが起きているため、deferされたrecoverは実行されない
golang.tokyo #15
問題
以下のテスト関数TestMyInt_Incが成功するように、Incメソッドを修正してください。 なお、Incメソッド以外は変更しないですください。
package main
import "testing"
type MyInt int
// テストが通るように以下のメソッドを修正させてください
func (n MyInt) Inc() {
n++
}
// テストは変更しないで下さい
func TestMyInt_Inc(t *testing.T) {
var n MyInt
n.Inc()
if n != 1 {
t.Errorf("want %d, got %d", 1, n)
}
n = 10
n.Inc()
if n != 11 {
t.Errorf("want %d, got %d", 11, n)
}
}
解答
修正箇所
// テストが通るように以下のメソッドを修正させてください
func (n *MyInt) Inc() {
*n++
}
- MyIntをポインタ渡しにするだけ
-
MyInt.Inc()
で結果を返すようにすると、カウントアップされた結果は返りますが、テストの修正が必要になるため、問題の条件を満たさないので、NG
golang.tokyo #16
問題
以下のテスト関数Testが成功するように、Stringメソッドを修正してください。 なお、Stringメソッド以外は変更しないでください。
package main
import (
"fmt"
"testing"
)
type Hex int
// テストが通るように以下のメソッドを修正させてください
func (h Hex) String() string {
return fmt.Sprintf("%x", h)
}
// テストは変更しないでください
func Test(t *testing.T) {
cases := map[string]struct {
h Hex
e string
}{
"100->64": {h: 100, e: "64"},
"16->10": {h: 16, e: "10"},
}
for n, tc := range cases {
t.Run(n, func(t *testing.T) {
if s := tc.h.String(); s != tc.e {
t.Errorf("want %q, got %q", tc.e, s)
}
})
}
}
解答
修正箇所
// テストが通るように以下のメソッドを修正させてください
func (h Hex) String() string {
return fmt.Sprintf("%x", int(h))
}
-
h
をint
にキャストする
golang.tokyo #17
問題
以下のテスト関数Testが成功するように、IsAllEven関数を修正してください。 なお、IsAllEven関数以外は変更しないでください
ヒント:初級者向けGoの落とし穴と解説 / Traps and Explanations in Go
package main
import (
"fmt"
"testing"
)
type ErrNotEven struct {
N int
}
func (err *ErrNotEven) Error() string {
return fmt.Sprintf("%d is not even", err.N)
}
// IsAllEvenだけを編集し、テストが通るようにしてください
func IsAllEven(ns ...int) error {
var err *ErrNotEven
for n := range ns {
if n%2 != 0 {
err = &ErrNotEven{N: n}
break
}
}
return err
}
func Test(t *testing.T) {
cases := map[string]struct {
ns []int
hasError bool
}{
"1,2,3": {ns: []int{0, 1, 2}, hasError: true},
"1,3,5": {ns: []int{1, 3, 5}, hasError: true},
"0,2,4": {ns: []int{2, 4, 6}, hasError: false},
}
for n, tc := range cases {
tc := tc
t.Run(n, func(t *testing.T) {
err := IsAllEven(tc.ns...)
switch {
case err != nil && !tc.hasError:
t.Error("unexpected error:", err)
case err == nil && tc.hasError:
t.Error("expected error has not occurred")
}
})
}
}
解答
修正箇所
// 修正前
var err *ErrNotEven
// 修正後
var err error
// 修正前
for n := range ns {
// 修正後
for _, n := range ns {
golang.tokyo #27
問題
以下のコードを実行すると何が出力されるか答えよ。
package main
import "fmt"
func main() {
switch ok := false; {
case true:
fmt.Println("true", ok)
case false:
fmt.Println("false", ok)
default:
fmt.Println("default")
}
}
解答
説明
内容としては、下記コードを実行したのと同じです。
okに代入しているだけで、switchの分岐条件には一切関与していません。
switchのデフォルトはtrueなので、 case true
に該当します。
package main
import "fmt"
func main() {
ok := false
switch {
case true:
fmt.Println("true", ok)
case false:
fmt.Println("false", ok)
default:
fmt.Println("default")
}
}