A Tour of GO
[A Tour of Go](https://go-tour-jp.appspot.com/methods/9 #)
#interface
インターフェース型と同じ関数を実装していない物はインターフェース型に代入できない
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
// MyFloatにはAbser()が実装されている
a = f
// *VertexにもAbser()は実装されている
a = &v
// aは*Vertexではないため、Aber()が実装されていない
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
}
// *vertexにはAbserと同じAbs()関数が実装されている
// Vertexのポインタ型に対して、実装している
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
#メソッドを実装し、インターフェースを実装する
type I interface {
M()
}
type T struct {
S string
}
// T に I(インターフェース)と同じメソッドを実装する
func (t T) M() {
fmt.Println(t.S)
}
func main() {
//TはIと同じメソッドを持っているので、I型と判断されるため、i(I型)に代入できる
var i I = T{"hello"}
i.M()
}
#Interface Values
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() // (&{Hello}, *main.T) Hello
//M() は元となるT型に宣言した同名のメソッドが呼び出される
i = F(math.Pi)
describe(i)
i.M() //(3.141592653589793, main.F) 3.141592653589793
//M() は元となるT型に宣言した同名のメソッドが呼び出される
}
Interface values with nil underlying values
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() {
// この時点ではiはnilである
var i I
// Tには何も入っていない,nilである
var t *T
// しかし、 iにはnilであるT型が入っているので、i自体は非nilである
i = t
describe(i) // (<nil>, *main.T) <nil>
i.M()
i = &T{"hello"}
describe(i) // (&{hello}, *main.T) <nil>
i.M()
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
#Nil interface values
type I interface {
M()
}
func main() {
//値も具体的な型も持っていない
var i I
describe(i)
i.M() // 何も値も持たないインターフェース型からはメソッドを呼べない
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
#The empty 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
string型をインターフェース型に変換した場合、
インターフェース型の中身が"hello"だったとしても、string型として扱うことができない。
そのため、再度インターフェース型からstring型に戻す作業が必要になる
func main() {
var i interface{} = "hello"
s := i.(string)
fmt.Println(s)
// okがiの中身がstring型値を保持しているかをboolで返す
s, ok := i.(string)
fmt.Println(s, ok)
f, ok := i.(float64)
fmt.Println(f, ok)
f = i.(float64) // panic
fmt.Println(f)
}
#Stringers
[fmtパッケージのソース](https://golang.org/src/fmt/print.go #)
Printlnメソッドが実行された時、引数がStringer型だったらstring()が実行されるはず
574行目あたりだろうか・・・
type Person struct {
Name string
Age int
}
//fmtのパッケージに以下の Stringer インターフェースの記述がある
************************************************************
type Stringer interface {
String() string
}
************************************************************
//Stringer型と同じString()メソッドを宣言すると Person型にStringerインターフェースを実装できる
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
組み込みのerrorインターフェースを実装し、エラーメッセージをカスタマイズする
type MyError struct {
When time.Time
What string
}
// error型のインターフェースを実装
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() {
// もし、run()で戻り値があったら、戻り値を出力
if err := run(); err != nil {
fmt.Println(err)
}
}
#Readers
func main() {
r := strings.NewReader("Hello, Reader!")
b := make([]byte, 8)
for {
// Readメソッドはint型とerror型の戻り値がある
n, err := r.Read(b)
fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
fmt.Printf("b[:n] = %q\n", b[:n])
//ストリームが終わったら、Readメソッドが返すio.EOFというエラーがerrに入るので、
//それを判定して、ループを抜ける
if err == io.EOF {
break
}
}
}
#Images
import (
"fmt"
"image"
)
*****************************************************************
*imageパッケージの中身
type Image interface {
ColorModel returns the Image's color model.
ColorModel() color.Model
//Bounds returns the domain for which At can return non-zero color.
// The bounds do not necessarily contain the point (0, 0).
Bounds() Rectangle
// At returns the color of the pixel at (x, y).
// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
At(x, y int) color.Color
}
type RGBA struct {
// Pix holds the image's pixels, in R, G, B, A order. The pixel at
// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
Pix []uint8
// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
Stride int
// Rect is the image's bounds.
Rect Rectangle
}
//RGBAにはAt, Boundes ColorModel()などのメソッドがあるので、Imageインターフェースが実装されている
func (p *RGBA) At(x, y int) color.Color
func (p *RGBA) ColorModel() color.Model
func (p *RGBA) Bounds() Rectangle
func Rect(x0, y0, x1, y1 int) Rectangle
//Rect is shorthand for Rectangle{Pt(x0, y0), Pt(x1, y1)}.
func NewRGBA(r Rectangle) *RGBA
//NewRGBA returns a new RGBA image with the given bounds.
*colorのパッケージ
type Color interface {
// RGBA returns the alpha-premultiplied red, green, blue and alpha values
// for the color. Each value ranges within [0, 0xffff], but is represented
// by a uint32 so that multiplying by a blend factor up to 0xffff will not
// overflow.
//
// An alpha-premultiplied color component c has been scaled by alpha (a),
// so has valid values 0 <= c <= a.
RGBA() (r, g, b, a uint32)
}
*****************************************************************
func main() {
// Rect()でRectange型の構造体を作成
// Rectange型を引数として、RGBA型の構造体を作成
m := image.NewRGBA(image.Rect(0, 0, 100, 100))
fmt.Println(m.Bounds())
fmt.Println(m.At(0, 0).RGBA())
}