Go Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

These steps cover writing and running your application:

  1. From your terminal/console application, create a new directory called chapter2/confformat and navigate to that directory.
  2. Copy tests from https://github.com/agtorre/go-cookbook/tree/master/chapter2/confformat, or use this as an exercise to write some of your own code!
  3. Create a file called toml.go with the following contents:
        package confformat

import (
"bytes"

"github.com/BurntSushi/toml"
)

// TOMLData is our common data struct
// with TOML struct tags
type TOMLData struct {
Name string `toml:"name"`
Age int `toml:"age"`
}

// ToTOML dumps the TOMLData struct to
// a TOML format bytes.Buffer
func (t *TOMLData) ToTOML() (*bytes.Buffer, error) {
b := &bytes.Buffer{}
encoder := toml.NewEncoder(b)

if err := encoder.Encode(t); err != nil {
return nil, err
}
return b, nil
}

// Decode will decode into TOMLData
func (t *TOMLData) Decode(data []byte) (toml.MetaData, error) {
return toml.Decode(string(data), t)
}
  1. Create a file called yaml.go with the following contents:
        package confformat

import (
"bytes"

"github.com/go-yaml/yaml"
)

// YAMLData is our common data struct
// with YAML struct tags
type YAMLData struct {
Name string `yaml:"name"`
Age int `yaml:"age"`
}

// ToYAML dumps the YAMLData struct to
// a YAML format bytes.Buffer
func (t *YAMLData) ToYAML() (*bytes.Buffer, error) {
d, err := yaml.Marshal(t)
if err != nil {
return nil, err
}

b := bytes.NewBuffer(d)

return b, nil
}

// Decode will decode into TOMLData
func (t *YAMLData) Decode(data []byte) error {
return yaml.Unmarshal(data, t)
}
  1. Create a file called json.go with the following contents:
        package confformat

import (
"bytes"
"encoding/json"
"fmt"
)

// JSONData is our common data struct
// with JSON struct tags
type JSONData struct {
Name string `json:"name"`
Age int `json:"age"`
}

// ToJSON dumps the JSONData struct to
// a JSON format bytes.Buffer
func (t *JSONData) ToJSON() (*bytes.Buffer, error) {
d, err := json.Marshal(t)
if err != nil {
return nil, err
}

b := bytes.NewBuffer(d)

return b, nil
}

// Decode will decode into JSONData
func (t *JSONData) Decode(data []byte) error {
return json.Unmarshal(data, t)
}

// OtherJSONExamples shows ways to use types
// beyond structs and other useful functions
func OtherJSONExamples() error {
res := make(map[string]string)
err := json.Unmarshal([]byte(`{"key": "value"}`), &res)
if err != nil {
return err
}

fmt.Println("We can unmarshal into a map instead of a
struct:", res)

b := bytes.NewReader([]byte(`{"key2": "value2"}`))
decoder := json.NewDecoder(b)

if err := decoder.Decode(&res); err != nil {
return err
}

fmt.Println("we can also use decoders/encoders to work with
streams:", res)

return nil
}
  1. Create a file called marshal.go with the following contents:
        package confformat

import "fmt"

// MarshalAll takes some data stored in structs
// and converts them to the various data formats
func MarshalAll() error {
t := TOMLData{
Name: "Name1",
Age: 20,
}

j := JSONData{
Name: "Name2",
Age: 30,
}

y := YAMLData{
Name: "Name3",
Age: 40,
}

tomlRes, err := t.ToTOML()
if err != nil {
return err
}

fmt.Println("TOML Marshal =", tomlRes.String())

jsonRes, err := j.ToJSON()
if err != nil {
return err
}

fmt.Println("JSON Marshal=", jsonRes.String())

yamlRes, err := y.ToYAML()
if err != nil {
return err
}

fmt.Println("YAML Marshal =", yamlRes.String())
return nil
}
  1. Create a file called unmarshal.go with the following contents:
        package confformat

import "fmt"

const (
exampleTOML = `name="Example1"
age=99
`

exampleJSON = `{"name":"Example2","age":98}`

exampleYAML = `name: Example3
age: 97
`
)

// UnmarshalAll takes data in various formats
// and converts them into structs
func UnmarshalAll() error {
t := TOMLData{}
j := JSONData{}
y := YAMLData{}

if _, err := t.Decode([]byte(exampleTOML)); err != nil {
return err
}
fmt.Println("TOML Unmarshal =", t)

if err := j.Decode([]byte(exampleJSON)); err != nil {
return err
}
fmt.Println("JSON Unmarshal =", j)

if err := y.Decode([]byte(exampleYAML)); err != nil {
return err
}
fmt.Println("Yaml Unmarshal =", y)
return nil
}
  1. Create a new directory named example.
  2. Navigate to example.
  3. Create a main.go file with the following contents and ensure that you modify the confformat import to use the path you set up in step 1:
        package main

import "github.com/agtorre/go-cookbook/chapter2/confformat"

func main() {
if err := confformat.MarshalAll(); err != nil {
panic(err)
}

if err := confformat.UnmarshalAll(); err != nil {
panic(err)
}

if err := confformat.OtherJSONExamples(); err != nil {
panic(err)
}
}
  1. Run go run main.go.
  2. You may also run these commands:
      go build
./example
  1. You should see the following:
      $ go run main.go
TOML Marshal = name = "Name1"
age = 20

JSON Marshal= {"name":"Name2","age":30}
YAML Marshal = name: Name3
age: 40

TOML Unmarshal = {Example1 99}
JSON Unmarshal = {Example2 98}
Yaml Unmarshal = {Example3 97}
We can unmarshal into a map instead of a struct: map[key:value]
we can also use decoders/encoders to work with streams:
map[key:value key2:value2]
  1. If you copied or wrote your own tests, go up one directory and run go test. Ensure all tests pass.