Skip to content

Instantly share code, notes, and snippets.

@k-hoshina
Created January 11, 2017 10:05
Show Gist options
  • Save k-hoshina/4b7f11428aac66fd5dce9cbe9aad0487 to your computer and use it in GitHub Desktop.
Save k-hoshina/4b7f11428aac66fd5dce9cbe9aad0487 to your computer and use it in GitHub Desktop.
interface{}のはなし

interface{}のはなし

goのinterfaceとは

方の定義とか関数の引数(あるいは帰り値)でよく使ってる

type Car interface {
  run(int)
  stop() bool
}
func dump(hoge interface{}){
  fmt.Printf("%#v\n", hoge)
}

interfaceを定義する

  • どのようなメソッドが実装されているか規定する仕組み
type Sounder interface {
	Sound()
}

func test(n Sounder) {
	n.Sound()
}

https://play.golang.org/p/nSXFEczoTj

代表的なinterface

  • errorはError()メソッドのみが要求される
type error interface{
  Error() string
}
  • Error()を実装するだけでかんたんに拡張できる
type MyError struct{
  Code int
  Src error
}

func (e *MyError) Error() string {
  return fmt.Sprintf("[%d] %s", e.Code, e.Src.Error())
}

func NewMyError(code int , e Error) MyError{
  return MyError{
    Code: code,
    Src: e,
  }
}

interface{}型

  • interface{}{} まで含めた一つの型の名前
  • goのすべての型と互換がある

interface{}はなんでも代入できる

var x interface{}
x = 1
x = "hoge"

引数interface{}はなんでも受け取れる

func dump(i interface{}){
	fmt.Printf("%v", i)
}

dump(1)
dump("hoge")
dump([]int{1,2,3})
dump(struct{ ID int }{ID: 1})

interface{}はメソッドを規定する

interface{}はメソッドを規定するものだということを思い出すと、つまり引数のinterface{}型でメソッドを規定することができる

package main

import (
	"fmt"
)

type Value struct {
	Num int
}

func (v Value) String() string {
	return fmt.Sprintf("Num is %d in String()", v.Num)
}

func (v Value) Text() string {
	return fmt.Sprintf("Num is %d in Text()", v.Num)
}

func testInterface(h interface { Text() string }) {
  fmt.Println(h.Text())
}

func testBlankInterface(i interface{}) {
	fmt.Println(i)
}

func main() {
	v := Value{Num: 100}

	testInterface(v)      // "Num is 100"
	testBlankInterface(v) // "Num is 100"
}

https://play.golang.org/p/cpGuzUdsmX

{interface { Text() string }型を引数に取るとText()メソッドが呼び出せる

fmy.Printlnは内部で type Stringer interface{String() string}を要求するためString()メソッドが呼び出される

つまり interface{}とは規定の型をもたないinterface{}型のこと

interface{}をつかう

型で挙動を分ける

func dump(x interface{}) {
	switch x.(type) {
	case string:
		fmt.Println("string")
	case int:
		fmt.Println("int")
	case MyType:
		fmt.Println("MyType")
	case MyInterface:
		fmt.Println("MyInterface")
	default:
		fmt.Println("unkown")

	}
}

https://play.golang.org/p/dbDIoSVZmv

指定された型で返す

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	var jsonBlob = []byte(`[
		{"Name": "Platypus", "Order": "Monotremata"},
		{"Name": "Quoll",    "Order": "Dasyuromorphia"}
	]`)
	type Animal struct {
		Name  string
		Order string
	}
	var animals []Animal
	err := json.Unmarshal(jsonBlob, &animals)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Printf("%+v", animals)
}
func Unmarshal(data []byte, v interface{}) error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment