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
あれ? 上手くいかんな。。。
ソフトウェアエンジニアの技術ブログ:Software engineer tech blog
随机应变 ABCD: Always Be Coding and … : хороший
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
あれ? 上手くいかんな。。。
公式のドキュメント: 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 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
ん? なんかオカシイ
### 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でもやりますか
– 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を使いこなすには 少し時間がかかりそうだ
### 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やったなあ
### 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のレベルが高いな
– 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って連想配列のような使い方ができるのね。
### Pointers
Go has pointers. A pointer holds the memory address of a value.
The type *T is a pointer to a T value. Its zero value is nil
func main(){ i, j := 42, 2701 p := &i fmt.Println(*p) *p = 21 fmt.Println(i) p = &j *p = *p / 37 fmt.Println(j) }
$ go build hello.go && ./hello
42
21
73
### Structs
A struct is a collection of fields.
type Vertex struct { X int Y int } func main(){ fmt.Println(Vertex{1, 2}) }
Struct fields are accessed using a dot.
type Vertex struct { X int Y int } func main(){ v := Vertex{1, 2} v.X = 4 fmt.Println(v.X) }
Pointers to structs
type Vertex struct { X int Y int } func main(){ v := Vertex{1, 2} p := &v p.X = 1e9 fmt.Println(v) }
$ go build hello.go && ./hello
{1000000000 2}
– Struct Literals
A struct literal donates a newly allocated struct value by listing the values of its fields.
var ( v1 = Vertex{1, 2} v2 = Vertex{X: 1} v3 = Vertex{} p = &Vertex{1, 2} ) func main(){ fmt.Println(v1, p, v2, v3) }
$ go build hello.go && ./hello
{1 2} &{1 2} {1 0} {0 0}
### Arrays
The type [n]T is an array of n values of type T.
func main(){ var a [2]string a[0] = "Hello" a[1] = "world" fmt.Println(a[0], a[1]) fmt.Println(a) primes := [6]int{2, 3, 5, 7, 11, 13} fmt.Println(primes) }
$ go build hello.go && ./hello
Hello world
[Hello world]
[2 3 5 7 11 13]
– Slices
An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array.
func main(){ primes := [6]int{2, 3, 5, 7, 11, 13} var s []int = primes[1:4] fmt.Println(s) }
– Slices are like references to arrays
A slice does not store any data, it just describes a section of an underlying array.
func main(){ names := [4]string{ "John", "Paul", "George", "Ringo", } fmt.Println(names) a := names[0:2] b := names[1:3] b[0] = "XXX" fmt.Println(a, b) fmt.Println(names) }
$ go build hello.go && ./hello
[John Paul George Ringo]
[John XXX] [XXX George]
[John XXX George Ringo]
– Slice literals
A slice literal is like an array literal without the length.
func main(){ q := []int{2, 3, 5, 7, 11, 13} fmt.Println(q) r := []bool{true, false, true, true, false, true} fmt.Println(r) s := []struct { i int b bool }{ {2, true}, {3, false}, {5, true}, {7, true}, {11, false}, {13, true}, } fmt.Println(s) }
C言語をやってからポインターは暫く離れていたが、Goもポインター使うのか。
### For
Go has only one looping construct, the for loop
func main(){ sum := 0; for i := 0; i < 10; i++ { sum += i } fmt.Println(sum) }
The init and post statements are optional
func main(){ sum := 1; for ; sum < 1000; { sum += sum } fmt.Println(sum) }
For is Go’s “while”
At that point you can drop the semicolons: C’s while is spelled for in Go.
func main(){ sum := 1; for sum < 1000 { sum += sum } fmt.Println(sum) }
### If
Go’s if statements are like its for loops.
func sqrt(x float64) string { if x < 0 { return sqrt(-x) + "i" } return fmt.Sprint(math.Sqrt(x)) } func main(){ fmt.Println(sqrt(2), sqrt(-4)) }
If with a short statement
func pow(x, n, lim float64) float64 { if v := math.Pow(x, n); v < lim { return v } else { fmt.Printf("%g >= %g\n", v, lim) } return lim } func main(){ fmt.Println( pow(3, 2, 10), pow(3, 3, 20), ) }
### Switch
A switch statement is a shorter way to write a sequence of if – else statements.
func main(){ fmt.Print("Go runs on ") switch os := runtime.GOOS; os{ case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: fmt.Println("%s.\n", os) } }
func main(){ fmt.Print("When's Saturday?") today := time.Now().Weekday() switch time.Saturday{ case today + 0: fmt.Println("Today.") case today + 1: fmt.Println("Tommorow.") case today + 2: fmt.Println("In two days.") default: fmt.Println("Too far away.") } }
func main(){ t := time.Now() switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } }
### Defer
A defer statement defers the execution of a function until the surrounding function returns.
func main(){ defer fmt.Println("wrold") fmt.Println("hello") }
$ go build hello.go && ./hello
hello
wrold
Stacking defers
L Deferred function calls are pushed onto a stack.
func main(){ fmt.Println("counting") for i := 0; i < 10; i++ { defer fmt.Println(i) } fmt.Println("done") }
deferってのは使い方がよくわからんが、最初は参照しながら書けば問題なさそうです。