package main

import "fmt"
import "io"
import "log"
import "reflect"
import "strings"
import "encoding/json"

type S struct{
	blah	int
	foo	string
}

func (s *S) addr() { fmt.Printf("%p\n", s) }

type Codec interface {
  Encode(w io.Writer, v interface{}) error
  Decode(r io.Reader, v interface{}) error
}

func (jsonCodec) Encode(w io.Writer, v interface{}) error {
	return json.NewEncoder(w).Encode(v)
}

func (jsonCodec) Decode(r io.Reader, v interface{}) error {
	return json.NewDecoder(r).Decode(v)
}

var JSON Codec = jsonCodec{}

type jsonCodec struct{}

type buttons interface {
	Encode(w io.Writer, v interface{}) error
	Decode(r io.Reader, v interface{}) error
}

type foo struct{}

type goo struct{
	test int
}

func bar(baz interface{}) {
	log.Println("baz =", baz)
	log.Println("reflect.TypeOf(baz) =", reflect.TypeOf(baz))
	switch f := baz.(type) {
	case int:
		log.Println("baz.(type) is an int =", f * 3)
	case *foo: // f is of type *foo
		log.Println("baz.(type) is known as *foo")
	default: // f is some other type
		log.Println("baz.(type) =", f)
	}

}


func main() {
        var a, b S
        a.addr() // 0x1beeb0
        b.addr() // 0x1beeb0

	f := &foo{}
	bar(f) // every type implements interface{}. Nothing special required

	g := &goo{}
	g.test = 4
	bar(g) // every type implements interface{}. Nothing special required

	bar("hello") // every type implements interface{}. Nothing special required

	// what is this?
//	s := &Service{
//		Codec: JSON,
//	}

	r := strings.NewReader("Hello, Reader!")
	err := JSON.Decode(r, "afjd")
	log.Println("JSON.Decoder err =", err)

	// err := JSON.Encode(w, obj)
	// log.Println("err =", err)

}