LoginSignup
0
0

More than 3 years have passed since last update.

A Tour of Go メモ 【7】五日目

Posted at

A Tour of GO

A Tour of Go

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パッケージのソース
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())
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0