👋

A Tour of Go

2024/03/18に公開

Go言語のツアー

Goのツアーやってたら課題が出てきたので、回答を残しとく

(Exercise: Loops and Functions)

package main

import (
	"fmt"
	"math"
)

// Exercise: Loops and Functions
func Sqrt(x float64) float64 {
	z := 1.0
	for i := 1; i <= 10; i++ {
		// ループは最大10回
		// ニュートン法の計算式
		z -= (z*z - x) / (2 * z)
		fmt.Println("Loop Count i=", i, "Calculation =", z)

		if math.Sqrt(x) == z {
			// ライブラリで変数xの平方根を計算し一致したらループ終了
			fmt.Println("Calculation has completed.")
			break
		}
	}
	return z
}

func main() {
	var target = 2.0
	calcvalue := Sqrt(target)
	libvalue := math.Sqrt(target)
	diff := calcvalue - libvalue

	fmt.Println("My Function Result=", calcvalue)
	fmt.Println("Library Result=", libvalue)
	fmt.Println("Diff", diff)
}
  • 振り返り
    • 問題文から要件を理解するのが一番時間かかったかも。
    • breakの条件でmath.Sqrt(x) == zとしたが、左辺はループの外に定義するか迷った

(Exercise: Slices)

package main

import (
	//"fmt"
	"golang.org/x/tour/pic"
)

func Pic(dx, dy int) [][]uint8 {
	// 親配列の長さ:dy :
	// 小配列の長さ:dx :
	sdy := make([][]uint8, dy)

	for i := range sdy {
		sdy[i] = make([]uint8, dx)
		for j := range sdy[i] {
			sdy[i][j] = uint8((i+j)/2)
		}
	}

	return sdy
}

func main() {
	//fmt.Println("main start")
	pic.Show(Pic)
}
  • 振り返り
    • varか:=か迷った。:=に寄せるほうが一般的らしい。
    • 未使用のインポートはエラーになるのが鬱陶しい。
    • print使ったら画像が表示されなかった。出力の根っこのところがそういう感じなんだろーなーで留めた。

(Exercise: Maps)

package main

import (
	"golang.org/x/tour/wc"
	"strings"
)

func WordCount(s string) map[string]int {
	words := strings.Fields(s)
	wordCountMap := make(map[string]int)
	count := 0

	for _, target := range words {
		for _, val := range words {
			if target == val {
				count++
			}
		}
		wordCountMap[target] = count
		count = 0
	}
	return wordCountMap
}

func main() {
	wc.Test(WordCount)
}
  • 振り返り

    • テスト駆動ってこういうのなのかな。最初何していいのかわからなかった。
    • 配列を検索する機能が標準でありそうだがみつからず。泥臭く実装した
  • レビューバック

    • 2回もループするなよ、と。修正してスッキリしたし処理回数も少なくなった。
package main

import (
	"golang.org/x/tour/wc"
	"strings"
)

func WordCount(s string) map[string]int {
	words := strings.Fields(s)
	wordCountMap := make(map[string]int)

	for _, target := range words {
        // ここを修正した
		wordCountMap[target] = wordCountMap[target] + 1
	}
	return wordCountMap
}

func main() {
	wc.Test(WordCount)
}

(Exercise: Fibonacci closure)

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	// フィボナッチ数列を格納する配列
	fibonaccilist := [] int{0,1}
	// 実行回数
	count := 0
	// (n + n-1)番目を格納する変数
	sum := 0

	return func() int {
		// (n+1 + n)番目を計算
		sum = fibonaccilist[count] + fibonaccilist[count+1]
		fibonaccilist = append(fibonaccilist,sum)
		// 実行回数インクリメント
		count++
		return fibonaccilist[count-1]
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}
  • 振り返り
    • どこを軸(配列の添字)にしてるのか、書いてて混乱した。
    • もう少しスッキリ書けないのか
  • レビューバック
    • 配列使わなくていい。そしてもっとスッキリ書ける。
package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	f0 := 0
	f1 := 1

	return func() int {
		// n+2番目を計算
		f2 := f0 + f1
		// n番目を返却する変数に退避
		x := f0
		// n+1番目をn番目に設定
		f0 = f1
		// n+2番目をn+1番目に設定
		f1 = f2
		return x
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}
  • 振り返り
    • 最低限の変数のみでスッキリ。何度実行してもメモリ使用量が一定なのがミソ。

(Exercise: Stringers)

package main

import "fmt"

type IPAddr [4]byte

// TODO: Add a "String() string" method to IPAddr.
func (ip IPAddr) String() string {
	return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
}

func main() {
	hosts := map[string]IPAddr{
		"loopback":  {127, 0, 0, 1},
		"googleDNS": {8, 8, 8, 8},
	}
	for name, ip := range hosts {
		fmt.Printf("%v: %v\n", name, ip)
	}
}
  • 振り返り
    • ポインター型にするとカンマが消える。なんで?(めも)
      • IPAddrがポインタ型ではない為

(Exercise: Errors)

package main

import (
	"fmt"
	"math"
)

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string {
	v := fmt.Sprint(float64(e))
	return fmt.Sprintf("cannot Sqrt negative number: %v", v)
}

func Sqrt(x float64) (float64, error) {
	z := 1.0
	var y float64

	if x < 0 {
		return x, ErrNegativeSqrt(x)
	}

	for i := 1; i <= 10; i++ {
		// ループは最大10回
		// 計算式
		y = (z*z - x) / (2 * z)
		z -= y
		fmt.Println("Loop Count i=", i, "Calculation =", z)

		if math.Sqrt(x) == z {
			// ライブラリと一致したらループ終了
			fmt.Println("Calculation has completed.")
			break
		}
	}
	return z, nil
}

func main() {
	fmt.Println(Sqrt(2.0))
	fmt.Println(Sqrt(-2))
}

(Exercise: Readers)

package main

import "golang.org/x/tour/reader"

type MyReader struct{}

// TODO: Add a Read([]byte) (int, error) method to MyReader.
func (r MyReader) Read(b []byte) (int, error) {
	for i, _ := range b {
		b[i] = 'A'
	}
	return len(b), nil
}

func main() {
	reader.Validate(MyReader{})
}

Discussion