[Go] Anacondaでtwitterのつぶやき取得

/home/vagrant/go/bin/dep init

twitterのconsumer key, access-tokenなどを用意します。

package main

import (
	"github.com/ChimeraCoder/anaconda"
)

func main() {
    anaconda.NewTwitterApiWithCredentials("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")
}

$ /home/vagrant/go/bin/dep ensure

作成されています。

twitterAccount.json

{
  "accessToken": "",
  "accessTokenSecret": "",
  "consumerKey": "",
  "consumerSecret": ""
}
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/ChimeraCoder/anaconda"
)

func main(){

	raw, error := ioutil.ReadFile("twitterAccount.json")

	if error != nil {
		fmt.Println(error.Error())
		return
	}

	var twitterAccount TwitterAccount
	json.Unmarshal(raw, &twitterAccount)

	api := anaconda.NewTwitterApiWithCredentials(twitterAccount.AccessToken, twitterAccount.AccessTokenSecret, twitterAccount.ConsumerKey, twitterAccount.ConsumerSecret)

	searchResult, _ := api.GetSearch(`スタートアップ`, nil)
	for _, tweet := range searchResult.Statuses {
		fmt.Println(tweet.Text)
	}
}

type TwitterAccount struct {
	AccessToken string `json:"accessToken"`
	AccessTokenSecret string `json:"accessTokenSecret"`
	ConsumerKey string `json:"consumerKey"`
	ConsumerSecret string `json:"consumerSecret"`
}

$ go run main.go
“厄介者”火山灰で排水処理を手助け、
巨大企業も目?
RT @ecoecoecho: 何をやっているか全く分からないが藤原竜也のイ
RT @Herlipto_info: 𝖲𝗁𝖺𝗋𝗂𝗇𝗀 𝗈𝗎𝗋 𝗅𝗈𝗏𝖾𝗅𝗒 𝗇𝖾𝗐 𝗉𝗂𝖾𝖼𝖾𝗌.

9/20(mon)20:00
RT @Herlipto_info: 𝖲𝗁𝖺𝗋𝗂𝗇𝗀 𝗈𝗎𝗋 𝗅𝗈𝗏𝖾𝗅𝗒 𝗇𝖾𝗐 𝗉𝗂𝖾𝖼𝖾𝗌.

// 省略

おおおおおおおおおおお

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/labstack/echo"
	"github.com/ChimeraCoder/anaconda"
)

func main(){

	e := echo.New()
	e.Post("/tweet", search)
	e.Logger.Fatal(e.start(":1323"))
}

func search(c echo.Context) error {
	keyword := c.FormValue("keyword")
	api := connectTwitterApi()

	searchResult, _ := api.GetSearch(`"` +keyword+ `"`, nil)

	tweets := make([]*Tweet, 0)

	for _, data := range searchResult.Statuses {
		tweet := new(Tweet)
		tweet.Text = data.FullText
		tweet.User = data.User.Name

		tweets = append(tweets, tweet)
	}

	return c.JSON(http.StatusOK, tweets)
}

func connectTwitterApi() *anaconda.TwitterApi {
	raw, error := ioutil.ReadFile("twitterAccount.json")

	if error != nil {
		fmt.Println(error.Error())
		return
	}

	var twitterAccount TwitterAccount
	json.Unmarshal(raw, &twitterAccount)

	return anaconda.NewTwitterApiWithCredentials(twitterAccount.AccessToken, twitterAccount.AccessTokenSecret, twitterAccount.ConsumerKey, twitterAccount.ConsumerSecret)

}



type TwitterAccount struct {
	AccessToken string `json:"accessToken"`
	AccessTokenSecret string `json:"accessTokenSecret"`
	ConsumerKey string `json:"consumerKey"`
	ConsumerSecret string `json:"consumerSecret"`
}

type Tweet struct {
	User string `json:"user"`
	Text string `json:"text"`
}

type Tweets *[]Tweet

$ go build
go: inconsistent vendoring in /home/vagrant/go/src/github.com/me/twitter:
github.com/ChimeraCoder/anaconda@v2.0.0+incompatible: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
github.com/ChimeraCoder/tokenbucket@v0.0.0-20131201223612-c5a927568de7: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
github.com/azr/backoff@v0.0.0-20160115115103-53511d3c7330: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
github.com/dustin/go-jsonpointer@v0.0.0-20160814072949-ba0abeacc3dc: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
github.com/dustin/gojson@v0.0.0-20160307161227-2e71ec9dd5ad: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
github.com/garyburd/go-oauth@v0.0.0-20180319155456-bca2e7f09a17: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
github.com/labstack/echo/v4@v4.5.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
golang.org/x/net@v0.0.0-20210917221730-978cfadd31cf: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt

run ‘go mod vendor’ to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory

なんでやろ
まあ 取得できるって事まではわかった。

[Go] Echoでルーティングを実装

### Get

import (
	"net/http"
	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()
	e.GET("/users/:name", getUserName)

	e.Logger.Fatal(e.Start(":1323"))
}

func getUserName(c echo.Context) error {
	name := c.Param("name")
	return c.JSON(http.StatusOK, name)
}

### QueryParamを使う場合

func main() {
	e := echo.New()
	e.GET("/show", show)

	e.Logger.Fatal(e.Start(":1323"))
}

func show(c echo.Context) error {
	team := c.QueryParam("team")
	member := c.QueryParam("member")
	return c.String(http.StatusOK, "team:"+team+", member:"+member)
}

http://192.168.33.10:1323/show?team=test&member=hpscript

### Post
FormValueで受け取る

func main() {
	e := echo.New()
	e.GET("/save", save)

	e.Logger.Fatal(e.Start(":1323"))
}

func save(c echo.Context) error {

	name := c.FormValue("name")
	email := c.FormValue("email")
	return c.String(http.StatusOK, "name:"+name+", email:"+email)
}

### JSONで返却

type User struct {
	Name string `json:"name"`
	Email string `json:"email"`
}

func main() {
	e := echo.New()
	e.GET("/users", saveUser)

	e.Logger.Fatal(e.Start(":1323"))
}

func saveUser(c echo.Context) error {

	u := new(User)
	if err := c.Bind(u); err != nil {
		return err
	}
	return c.JSON(http.StatusOK, u)
}
type Message struct {
	Name string `json:"name"`
	Email string `json:"email"`
	Message string `json:"message"`
}

type Response struct {
	Name string `json:"name"`
	Email string `json:"email"`
	Message string `json:message`
	Status string `json:status`
}

func main() {
	e := echo.New()
	e.GET("/send", sendMessage)

	e.Logger.Fatal(e.Start(":1323"))
}

func sendMessage(c echo.Context) error {

	m := new(Message)
	if error := c.Bind(m); error != nil {
		return error
	}
	r := new(Response)
	r.Name = m.Name
	r.Email = m.Email
	r.Message = m.Message
	r.Status = "success"
	return c.JSON(http.StatusOK, r)
}

なるほど、ルーティングの機能についてはある程度わかりました。
MVCに分かれているのではなく、1枚のファイルの中に書いていくのね。

[Go] Firebaseとの連結

Firebaseで Firestoreを作成する

import (
	"fmt"

	firebase "firebase.google.com/go"
    "google.golang.org/api/option"
)

func main(){
	fmt.Printf("Hello Firestore")
}

必要な依存関係を追加
$ go get firebase.google.com/go

あれ? 上手くいかんな。。。

[Go] パッケージ管理のdepを使う

公式のドキュメント: dep
git hub: https://github.com/golang/dep

### Binary installation
$ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5230 100 5230 0 0 7623 0 –:–:– –:–:– –:–:– 7612
ARCH = amd64
OS = linux
Will install into /home/vagrant/go/bin
Fetching https://github.com/golang/dep/releases/latest..
Release Tag = v0.5.4
Fetching https://github.com/golang/dep/releases/tag/v0.5.4..
Fetching https://github.com/golang/dep/releases/download/v0.5.4/dep-linux-amd64..
Setting executable permissions.
Moving executable to /home/vagrant/go/bin/dep

どうやら、私のケースでは /home/vagrant/go/bin/depにあるよう

$ /home/vagrant/go/bin/dep version
dep:
version : devel
build date :
git hash :
go version : go1.15.14
go compiler : gc
platform : linux/amd64
features : ImportDuringSolve=false
$ mkdir -p /home/vagrant/go/src/github.com/me/example
$ cd /home/vagrant/go/src/github.com/me/example
$ /home/vagrant/go/bin/dep init
$ ls
Gopkg.lock Gopkg.toml vendor

main.go

package main

import (
	"fmt"
	
	"github.com/carlescere/scheduler"
	"runtime"
)

func main(){
	scheduler.Every(3).Seconds().Run(printSuccess)
	runtime.Goexit()
}

func printSuccess(){
	fmt.Printf("Success!! \n")
}

$ go run main.go
main.go:6:2: cannot find package “github.com/carlescere/scheduler” in any of:
/home/vagrant/go/src/github.com/me/example/vendor/github.com/carlescere/scheduler (vendor tree)
/usr/lib/golang/src/github.com/carlescere/scheduler (from $GOROOT)
/home/vagrant/go/src/github.com/carlescere/scheduler (from $GOPATH)

このままでは 以下のようにcannot findとなるのでensureする
$ /home/vagrant/go/bin/dep ensure

$ go run main.go
Success!!
Success!!
Success!!
Success!!
Success!!
Success!!

なるほど、phpでいうcomposerみたいなものか
素晴らしい

[Go] Echoを使いたい

$ go version
go version go1.15.14 linux/amd64

$ mkdir myapp && cd myapp
$ go mod init myapp
$ ls
go.mod

module myapp

go 1.15

$ go get github.com/labstack/echo/v4
$ ls
go.mod go.sum

server.go

package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error{
		return c.String(http.StatusOK, "Hello, Echo")
	})
	e.Logger.Fatal(e.Start(":1323"))
}

$ go run server.go

type User struct {
	Name string `json:"name"`
	Email string `json:"email"`
}

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error{
		return c.String(http.StatusOK, "Hello, Echo")
	})
	e.GET("/user", show)

	e.Logger.Fatal(e.Start(":1323"))
}

func show(c echo.Context) error {
	u := new(User)
	if err := c.Bind(u); err != nil {
		return err
	}
	return c.JSON(http.StatusOK, u)
}

http://192.168.33.10:1323/user?name=hpscript&email=info@hpscript.com

ん? なんかオカシイ

[Go] Concurrency

### Goroutines
A goroutine is a lightweight thread managed by Go runtime.

func say(s string){
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main(){
	go say("world")
	say("hello")
}

### Channels
Channels are a typed conduit through which you can send and receive values with the channel operator

func sum(s []int, c chan int){
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum
}

func main(){
	s := []int{7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := <-c, <-c

	fmt.Println(x, y, x+y)
}

Buffered Channels

func main(){
	ch := make(chan int, 2)
	ch <- 1
	ch <- 2

	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

– Range and close
A sender can close a channel to indicate that no more values will sent. Receivers can test whether a channel has been closed by assigning a second parameter to the receive expression: after

func fibonacci(n int, c chan int){
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	close(c)
}

func main(){
	c := make(chan int, 10)
	go fibonacci(cap(c), c)
	for i := range c{
		fmt.Println(i)
	}
}

### Select
The select statement lets a goroutine wait on multiple communication operations.

func fibonacci(c, quit chan int){
	x, y := 0, 1
	for {
		select {
		case c <- x:
			x, y = y, x+y
		case <-quit:
			fmt.Println("quit")
			return
		}
	}
}

func main(){
	c := make(chan int)
	quit := make(chan int)
	go func(){
		for i := 0; i < 10; i++ {
			fmt.Println(<-c)
		}
		quit <- 0
	}()
	fibonacci(c, quit)
}

Default Selection

func main(){
	tick := time.Tick(100 * time.Millisecond)
	boom := time.After(500 * time.Millisecond)
	for {
		select {
		case <-tick:
			fmt.Println("tick.")
		case <-boom:
			fmt.Println("BOOM!")
			return
		default:
			fmt.Println("   .")
			time.Sleep(50 * time.Millisecond)
		}
	}
}

– sync.Mutex

type SafeCounter struct {
	mu sync.Mutex
	v map[string]int
}

func (c *SafeCounter) Inc(key string){
	c.mu.Lock()
	c.v[key]++
	c.mu.Unlock()
}

func(c *SafeCounter) Value(key string) int {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.v[key]
}

func main(){
	c := SafeCounter{v: make(map[string]int)}
	for i := 0; i < 1000; i++ {
		go c.Inc("somekey")
	}

	time.Sleep(time.Second)
	fmt.Println(c.Value("somekey"))
}

それではEchoでもやりますか

[Go] Methods and Interfaces その2

– Interface values with nil underlying values
If the concrete value inside the interface itself is nil, the method will be called with a nil receiver.

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M(){
	if t == nil {
		fmt.Println("<nil>")
		return
	}
	fmt.Println(t.S)
}

func main(){
	var i I

	var t *T
	i = t
	describe(i)
	i.M()

	i = &T{"hello"}
	describe(i)
	i.M()
}

func describe(i I){
	fmt.Printf("(%v, %T)\n", i, i)
}

– Nil interface values
A nil interface value holds neither value nor concrete type.

type I interface {
	M()
}

func main(){
	var i I

	describe(i)
	i.M()
}

func describe(i I){
	fmt.Printf("(%v, %T)\n", i, i)
}

(, )
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x49abcf]

goroutine 1 [running]:
main.main()
/home/vagrant/next/go/hello.go:14 +0x8f

– The empty interface
The interface type that specifies zero methods is known as the empty interface: interface{}

func main(){
	var i interface{}
	describe(i)

	i = 42
	describe(i)

	i = "hello"
	describe(i)
}

func describe(i interface{}){
	fmt.Printf("(%v, %T)\n", i, i)
}

– Type assertions
A type assertion provides access to an interface value’s underlying concrete value.

func main(){
	var i interface{} = "hello"
	
	s := i.(string)
	fmt.Println(s)

	s, ok := i.(string)
	fmt.Println(s, ok)

	f, ok := i.(float64)
	fmt.Println(f, ok)

	f = i.(float64)
	fmt.Println(f)
}

– Type switches
A type switch is a construct that permits several type assertions in series.

func do(i interface{}){
	switch v := i.(type){
	case int:
		fmt.Printf("Twice %v is %v\n", v, v*2)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v))
	default:
		fmt.Printf("I don't know about type %T!\n", v)
	}
}

func main(){
	do(21)
	do("hello")
	do(true)
}

– Stringers
A stringer is a type that can describe itself as a string. The fmt package look for this interface to print values.

type Person struct {
	Name string
	Age int
}

func (p Person) String() string {
	return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main(){
	a := Person{"Arthur Dent", 42}
	z := Person{"Zaphod Beeblebrox", 9001}
	fmt.Println(a, z)
}

### Errors
Go programs express error state with error values.

type MyError struct {
	When time.Time
	What string
}

func (e *MyError) Error() string{
	return fmt.Sprintf("at %v, %s", e.When, e.What)
}

func run() error {
	return &MyError {
		time.Now(),
		"it didn't work",
	}
}

func main(){
	if err := run(); err != nil {
		fmt.Println(err)
	}
}

### Readers
The io package specifies the io.Reader interface, which represents the read end of a stream of data.

import (
	"fmt"
	"io"
	"strings"
)

func main(){
	r := strings.NewReader("Hello, Reader!")

	b := make([]byte, 8)
	for {
		n, err := r.Raed(b)
		fmt.Printf("n = %v err = %v b= %v\n", n, err, b)
		fmt.Printf("b[:n] = %q\n", b[:n])
		if err == io.EOF {
			break
		}
	}
}

### Images

import (
	"fmt"
	"image"
)

func main(){
	m := image.NewRGBA(image.Rect(0, 0, 100, 100))
	fmt.Println(m.Bounds())
	fmt.Println(m.At(0, 0).RGBA())
}

Methods と Interfaceを使いこなすには 少し時間がかかりそうだ

[Go] Methods and Interfaces その1

### Method
A method is a function with a special receiver argument.

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main(){
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}

– Methods are functions
You can declare a method on non-struct types, too.

type MyFloat float64

func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

func main(){
	f := MyFloat(-math.Sqrt2)
	fmt.Println(f.Abs())
}

– Pointer receivers
You can declare methods with pointer receivers.

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vertex) Scale(f float64){
	v.X = v.X * f
	v.Y = v.Y * f
}

func main(){
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Abs())
}

### Interface
An interface type is defined as a set of method signatures

type Abser interface {
	Abs() float64
}

func main(){
	var a Abser
	f := MyFloat(-math.Sqrt2)
	v := Vertex{3, 4}

	a = f
	a = &v

	a = v

	fmt.Println(a.Abs())
}

type MyFloat float64

func(f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

type Vertex struct {
	X, Y float64
}

func(v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

# command-line-arguments
./hello.go:19:4: cannot use v (type Vertex) as type Abser in assignment:
Vertex does not implement Abser (Abs method has pointer receiver)

– Interfaces are implemented implicitly
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no “implements” keyword.

type I interface {
	M()
}

type T struct {
	S string
}

func (t T) M(){
	fmt.Println(t.S)
}

func main(){
	var i I = T{"hello"}
	i.M()
}

– Interface values
Under the hood, interface values can be thought of as a tuple of value and a concrete type.

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M(){
	fmt.Println(t.S)
}

type F float64

func(f F) M(){
	fmt.Println(f)
}

func main(){
	var i I
	i = &T{"hello"}
	describe(i)
	i.M()

	i = F(math.Pi)
	describe(i)
	i.M()
}

func describe(i I){
	fmt.Printf("(%v, %T)\n", i, i)
}

interfaceやったなあ

[Go] structs, slices, and maps その3

### Maps
A map maps key to values.

type Vertex struct {
	Lat, Long float64
}

var m map[string]Vertex

func main(){
	m = make(map[string]Vertex)
	m["Bell Labs"] = Vertex{
		40.68433, -74.39967,
	}
	fmt.Println(m["Bell Labs"])
}

– Map leterals
Map literals are like struct literals, but the keys are requried

type Vertex struct {
	Lat, Long float64
}

var m = map[string]Vertex{
	"Bell Labs" : Vertex{
		40.68433, -74.39967,
	},
	"Google": Vertex {
		37.42202, -122.08408,
	},
}

func main(){	
	fmt.Println(m)
}

– Map literals continued
If the top-level type is just a type name, you can omit it from the elements of the literal.

– Mutating Maps
Insert, Retrieve, Delete

func main(){
	m := make(map[string]int)

	m["Answer"] = 42	
	fmt.Println("The value:", m["Answer"])

	m["Answer"] = 48
	fmt.Println("The value:", m["Answer"])

	delete(m, "Answer")
	fmt.Println("The value:", m["Answer"])

	v, ok := m["Answer"]
	fmt.Println("The value:", v, "Present?", ok)
}

### Function values
Functions are values too. They can be passed around just like other values. Function values may be used as function arguments and return values.

func compute(fn func(float64, float64) float64) float64 {
	return fn(3, 4)
}

func main(){
	hypot := func(x, y float64) float64 {
		return math.Sqrt(x*x + y*y)
	}

	fmt.Println(hypot(5, 12))

	fmt.Println(compute(hypot))
	fmt.Println(compute(math.Pow))
}

– Function closures
A closure is a function value that references variables from outside its body. The function may access and assign to the referenced variables.

func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func main(){
	pos, neg := adder(), adder()
	for i := 0; i<10; i++ {
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	}
}

$ go build hello.go && ./hello
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90

うむ、GoにもなるとTutorialのレベルが高いな

[Go] structs, slices, and maps その2

– Slice default
When slicing, you may omit the high or low bounds to use their defaults instead.

func main(){
	s := []int{2, 3, 5, 7, 11, 13}

	s = s[1:4]
	fmt.Println(s)

	s = s[:2]
	fmt.Println(s)

	s = s[1:]
	fmt.Println(s)
}

– Slice length and capacity
The length of a slice is the number of elements it contains. The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.

func main(){
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	s = s[:0]
	printSlice(s)

	s = s[:4]
	printSlice(s)

	s = s[2:]
	printSlice(s)
}

func printSlice(s []int){
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

$ go build hello.go && ./hello
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

Nil slices
– The zero value of a slice is nil.

func main(){
	var s[]int
	fmt.Println(s, len(s), cap(s))
	if s == nil {
		fmt.Println("nil!")
	}
}

– Creating a slice with make
The make function allocate a zeroed array and returns a slice that refers to that array.

func main(){
	a := make([]int, 5)
	printSlice("a", a)

	b := make([]int, 0, 5)
	printSlice("b", b)

	c := b[:2]
	printSlice("c", c)

	d := c[2:5]
	printSlice("d", d)
}


func printSlice(s string, x []int){
	fmt.Printf("%s len=%d cap=%d %v\n", s, len(x), cap(x), x)
}

$ go build hello.go && ./hello
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []

– Slices of slices
Slices can contain any type, including other slices.

func main(){
	board := [][]string {
		[]string{"_","_","_"},
		[]string{"_","_","_"},
		[]string{"_","_","_"},
	}

	board[0][0] = "X"
	board[2][2] = "0"
	board[1][2] = "X"
	board[1][0] = "0"
	board[0][2] = "X"

	for i := 0; i < len(board); i++ {
		fmt.Printf("%s\n", strings.Join(board[i], " "))
	}
}

$ go build hello.go && ./hello
X _ X
0 _ X
_ _ 0

– Appending to a slice
It is common to append new elements to a slice, and so Go provides a built-in append function.

func main(){
	var s []int
	printSlice(s)

	s = append(s, 0)
	printSlice(s)

	s = append(s, 1)
	printSlice(s)

	s = append(s, 2, 3, 4)
	printSlice(s)
}

func printSlice(s []int){
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

### Range
When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main(){
	for i, v := range pow {
		fmt.Printf("2**%d = %d\n", i, v)
	}
}

$ go build hello.go && ./hello
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128

– Range continued
You can skip the index or value by assigning to _.

func main(){
	pow := make([]int, 10)
	for i := range pow {
		pow[i] = 1 << uint(i) // == 2**i
	}
	for _, value := range pow {
		fmt.Printf("%d\n", value)
	}
}

なるほど、Sliceって連想配列のような使い方ができるのね。