Golang nested map filter - go

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
fmt.Println(fecthData())
}
func fecthData() (map[string]interface{}, error) {
body := strings.NewReader("dil_kodu=tr")
req, err := http.NewRequest("POST", "https://www.haremaltin.com/dashboard/ajax/doviz", body)
if err != nil {
// handle err
return nil, err
}
req.Header.Set("X-Requested-With", "XMLHttpRequest")
resp, err := http.DefaultClient.Do(req)
if err != nil {
// handle err
return nil, err
}
defer resp.Body.Close()
jsonData, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
return nil, err
}
var data map[string]interface{}
err = json.Unmarshal(jsonData, &data)
if err != nil {
return nil, err
}
return data, nil
}
You can see full code above and I have a go response as below and it is nested map as you see and want to reach "data-ATA5_ESKI-satis" value which is 34319. Is there anybody to help me.
Thank you for your time
A part of response below:
map[data:map[AEDTRY:map[alis:4.6271 code:AEDTRY dir:map[alis_dir: satis_dir:] dusuk:4.7116 kapanis:4.6224 satis:4.7271 tarih:17-06-2022 19:41:45 yuksek:4.7276] AEDUSD:map[alis:0.2680 code:AEDUSD dir:map[alis_dir: satis_dir:] dusuk:0.27 kapanis:0.268 satis:0.2700 tarih:17-06-2022 19:30:02 yuksek:0.27]... ALTIN:map[alis:1024.790 code:ALTIN dir:map[alis_dir:down satis_dir:down] dusuk:1029.05 kapanis:1032.13 satis:1030.650 tarih:17-06-2022 19:41:58 yuksek:1040] ATA5_ESKI:map[alis:33869 code:ATA5_ESKI dir:map[alis_dir:down satis_dir:down] dusuk:34266 kapanis:34112 satis:34319 tarih:17-06-2022 19:41:58 yuksek:34630] XPTUSD:map[alis:933 code:XPTUSD dir:map[alis_dir: satis_dir:] dusuk:936 kapanis:953 satis:936 tarih:17-06-2022 19:41:58 yuksek:957]] meta:map[fiyat_guncelleme:2000 fiyat_yayini:web_socket time:1.655484118278e+12 time_formatted:]]

for _, v := range data { // we need value part of the map
m, ok := v.(map[string]interface{}) // we need the convert the map
// into interface for iteration
if !ok {
fmt.Printf("Error %T", v)
}
for k, l := range m {
if k == "ATA_ESKI"{ // the value we want is inside of this map
a, ok := l.(map[string]interface{}) // interface convert again
if !ok {
fmt.Printf("Error %T", v)
}
for b,c := range a{
if b == "satis"{ // the value we want
fmt.Println("Price is", c)
}
}
}
}
}
We can get the value adding this iteration before "return data, nil" at the end but I think there must be easier methods for this.

Related

Zip a slice of byte into another slice in Golang

I want to achieve exactly opposite of the solution given here, zipping a slice of byte into another slice of byte -
Convert zipped []byte to unzip []byte golang code
Something like -
func ZipBytes(unippedBytes []byte) ([]byte, error) {
// ...
}
[I am going to upload that zipped file as multipart form data for a POST request]
You can compress directly into memory using a bytes.Buffer.
The following example uses compress/zlib since it is the opposite of the example given in the question. Depending on your use case you could easily change it to compress/gzip as well (very similar APIs).
package data_test
import (
"bytes"
"compress/zlib"
"io"
"testing"
)
func compress(buf []byte) ([]byte, error) {
var out bytes.Buffer
w := zlib.NewWriter(&out)
if _, err := w.Write(buf); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
return out.Bytes(), nil
}
func decompress(buf []byte) (_ []byte, e error) {
r, err := zlib.NewReader(bytes.NewReader(buf))
if err != nil {
return nil, err
}
defer func() {
if err := r.Close(); e == nil {
e = err
}
}()
return io.ReadAll(r)
}
func TestRoundtrip(t *testing.T) {
want := []byte("test data")
zdata, err := compress(want)
if err != nil {
t.Fatalf("compress: %v", err)
}
got, err := decompress(zdata)
if err != nil {
t.Fatalf("decompress: %v", err)
}
if !bytes.Equal(want, got) {
t.Errorf("roundtrip: got = %q; want = %q", got, want)
}
}

Ethereum error {"code":-32000,"message":"unknown account"}

I am trying to send a raw transaction with eth.sendTransaction but I am getting an error that says {"code":-32000,"message":"unknown account"}. I am not sure what is causing this and I cant seem to find an answer on the internet. Can anyone help me figure it out? Here is my code:
func ExecuteSignedTransaction(rawTransaction string) {
var hash web3.Hash
data := make(map[string]interface{})
data["data"] = rawTransaction
err := Web3HTTPClient.Call("eth_sendTransaction", &hash, data)
if err != nil{
fmt.Println(err)
Os.Exit(1)
}
fmt.Println("Sent tx hash:", hash)
}
So, what I might do here:
import (
"strings"
"crypto/ecdsa"
"math/big"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
)
var chainId = big.NewInt(1) // chain id for the ethereum mainnet, change according to needs
func ecdsaPrivateKeyFromHex(privKeyHex string) *ecdsa.PrivateKey {
ecdsaKey, err := crypto.HexToECDSA(privKeyHex)
if err != nil { panic(err) }
return ecdsaKey
}
func newTransactOpts(privKey *ecdsa.PrivateKey) *bind.TransactOpts {
transactOpts, err := bind.NewKeyedTransactorWithChainID(privKey, chainId)
if err != nil { panic(err) }
return transactOpts
}
func newRpcClient() *ethclient.Client {
c, err := ethclient.Dial("insert rpc url here")
if err != nil { panic(err) }
return c
}
// note: constructing the *types.Transaction object left as
// an exercise to the reader
func ExecuteTransaction(rawTransaction *types.Transaction) {
privKeyHex := "0xblahblahblahblahblah" // use your own account's private key
transactOpts := newTransactOpts(ecdsaPrivateKeyFromHex(privKeyHex))
signedTxn, err := transactOpts.Signer(transactOpts.From, rawTransaction)
if err != nil { panic(err) }
rpcClient := newRpcClient()
if err := rpcClient.SendTransaction(context.Background(), signedTxn); err != nil { panic(err) }
// do whatever
}

Inadvertent multiple returns

I'm building an application where I get muslim prayer data from multiple sources. The first being S3, the second being aladhan (a public api). I only want to get data from aladhan if it's not available in S3. If I do have to get the data from the public source then I upload it to my s3.
Here is the code:
This is my interface loop code. I've put in print statements to show that I'm running into the return statement twice, once with data in my return struct, the second time the struct is nil.
// prayeriface.go
package prayer
import (
"fmt"
)
type MonthPrayerIface interface {
GetMonthPrayer(input *LookupInput) (*PreCurrNextMonthPrayer, error)
}
type PreCurrNextMonthPrayer struct {
custData *LookupInput
CurrentMonthData *PCal
PreviousMonthData *PCal
NextMonthData *PCal
prayers []MonthPrayerIface
}
func (p *PreCurrNextMonthPrayer) GetMonthPrayers() (*PreCurrNextMonthPrayer, error) {
var err error
var monthlyData *PreCurrNextMonthPrayer
defer func() {
fmt.Printf("return monthlyData address & value = %p %v\n", monthlyData, monthlyData)
}()
for k, data := range p.prayers {
fmt.Printf("loop = %v, data= %T %v\n", k, monthlyData, monthlyData)
monthlyData, err = data.GetMonthPrayer(p.custData)
fmt.Printf("\terr= %v\n", err)
fmt.Printf("\tmonthlyData= %p %v\n", monthlyData, monthlyData)
if err == nil {
fmt.Printf("loop-return: err == nil \n")
return monthlyData, nil
}
}
if err == nil {
fmt.Printf("post-loop:\n")
fmt.Printf("\tmonthlyData= %p %v\n", monthlyData, monthlyData)
return monthlyData, nil
}
return nil, fmt.Errorf("unable to get prayer data from all sources %s", err)
}
func NewMonthPrayer(input *LookupInput, prayers ...MonthPrayerIface) (*PreCurrNextMonthPrayer, error) {
var err error
t := &PreCurrNextMonthPrayer{
custData: input,
prayers: prayers,
}
t, err = t.GetMonthPrayers()
if err != nil {
return nil, err
}
return t, nil
}
As you can see, I'm looping over an interface struct method called GetMonthPrayer
This is my s3 source
// s3.go
package prayer
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"io"
awsservices "prayer-times/src/aws"
)
// S3Store s3 storage object for prayer calendars
type S3Store struct {
data *PCal
}
// GetMonthPrayer retrieves prayer data from s3, otherwise from aladhan
func (s *S3Store) GetMonthPrayer(input *LookupInput) (*PreCurrNextMonthPrayer, error) {
mPrayer := new(PreCurrNextMonthPrayer)
fmt.Println("attempting to retrieve prayer data from s3")
s3Client := awsservices.NewS3Service()
pMonthInput := &LookupInput{
Country: input.Country,
ZipCode: input.ZipCode,
custTime: input.custTime.AddDate(0, -1, 0),
}
nMonthInput := &LookupInput{
Country: input.Country,
ZipCode: input.ZipCode,
custTime: input.custTime.AddDate(0, 1, 0),
}
// s3Pdata retrieves data from S3 and
s3pData := func(input *LookupInput) (*PCal, error) {
pCalendar := new(PCal)
data, err := s3Client.GetObject(&s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(
fmt.Sprintf(
"%s/%d/%d/%d",
input.Country,
input.ZipCode,
input.custTime.Year(),
input.custTime.Month())),
})
if err != nil {
return nil, err
}
if data == nil {
return nil, errors.New("error data from s3 is nil")
}
defer func() {
err := data.Body.Close()
if err != nil {
fmt.Printf("unable to close s3 body: %s", err)
}
}()
s3buf := bytes.NewBuffer(nil)
if _, err := io.Copy(s3buf, data.Body); err != nil {
return nil, err
}
dataBytes := s3buf.Bytes()
decoder := json.NewDecoder(bytes.NewReader(dataBytes))
err = decoder.Decode(&pCalendar)
if err != nil {
fmt.Printf("unable to decode json: %s", err)
}
return pCalendar, nil
}
aladhanData := new(AladhanStore)
getAladhanData := func(input *LookupInput) (*PreCurrNextMonthPrayer, error) {
data, err := aladhanData.GetMonthPrayer(input)
if err != nil {
return nil, err
}
return data, nil
}
// Get current data from s3, if not s3, then get all three from aladhan
cMonthS3Data, err := s3pData(input)
pMonthS3Data, err := s3pData(pMonthInput)
nMonthS3Data, err := s3pData(nMonthInput)
if err != nil {
adata, err := getAladhanData(input)
if err != nil {
fmt.Printf("err: %s", err)
return nil, err
}
return adata, nil
}
mPrayer.CurrentMonthData = cMonthS3Data
// Get previous month data from s3, if not s3, then get all three from aladhan
mPrayer.PreviousMonthData = pMonthS3Data
// Get next month data from s3, if not s3, then get all three from aladhan
mPrayer.NextMonthData = nMonthS3Data
return mPrayer, nil
}
Here is my aladhan source
// aladhan.go
package prayer
import (
"bytes"
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"golang.org/x/sync/errgroup"
"io"
"log"
awsservices "prayer-times/src/aws"
"prayer-times/src/urljsonoutput"
"prayer-times/src/zipcoordinates"
)
var (
aladhanURL string = "https://api.aladhan.com/v1/calendar?"
)
// PCal contains the prayer times of the month as well as the return code
type PCal struct {
Code int `json:"code"`
Status string `json:"status"`
Data []struct {
Timings DailyPrayers
}
}
/*
AladhanData returns the total monthly prayers of given month, coordinates, and zip from aladhan.
https://api.aladhan.com/v1/calendar?latitude=51.508515&longitude=-0.1254872&method=1&month=4&year=2017
*/
func AladhanData(input *LookupInput) *PCal {
coordinates := zipcoordinates.HereCoordinates(&zipcoordinates.GeoLocationInput{
PostalCode: input.ZipCode,
CountryCode: input.Country,
})
respStruct := new(PCal)
_, err := urljsonoutput.GetURLJSON(fmt.Sprintf(
"%slatitude=%v&longitude=%v&method=%v&month=%v&year=%v",
aladhanURL,
coordinates.Items[0].Position.Latitude,
coordinates.Items[0].Position.Longitude,
input.Method,
int(input.custTime.Month()),
input.custTime.Year()), respStruct)
if err != nil {
log.Fatalf("unable to pull monthly prayer data %v", err)
}
return respStruct
}
// AladhanStore struct to interact with interface for GetMonthPrayer
type AladhanStore struct {
data *PCal
}
// GetMonthPrayer Pulls prayer data from aladhan
func (a *AladhanStore) GetMonthPrayer(input *LookupInput) (*PreCurrNextMonthPrayer, error) {
mPrayer := new(PreCurrNextMonthPrayer)
// Return prayer data from aladhan
custPMonthTime := input.custTime.AddDate(0, -1, 0)
pMonthLookupInput := new(LookupInput)
pMonthLookupInput.custTime = custPMonthTime
pMonthLookupInput.ZipCode = input.ZipCode
pMonthLookupInput.Country = input.Country
custNMonthTime := input.custTime.AddDate(0, 1, 0)
nMonthLookupInput := new(LookupInput)
nMonthLookupInput.custTime = custNMonthTime
nMonthLookupInput.ZipCode = input.ZipCode
nMonthLookupInput.Country = input.Country
prayerData := AladhanData(input)
pMonthPData := AladhanData(pMonthLookupInput)
nMonthPData := AladhanData(nMonthLookupInput)
// Save prayer data into io.Reader to save to s3
var Marshal = func(data interface{}) (io.ReadSeeker, error) {
mdata, err := json.MarshalIndent(data, "", "\t")
if err != nil {
return nil, err
}
return bytes.NewReader(mdata), nil
}
rmData, err := Marshal(prayerData)
pRmData, err := Marshal(pMonthPData)
nRmData, err := Marshal(nMonthPData)
if err != nil {
return nil, err
}
// Save prayer data into s3
g := new(errgroup.Group)
s3Upload := func(rawData *io.ReadSeeker, input *LookupInput) func() error {
return func() error {
s3Client := s3manager.NewUploaderWithClient(awsservices.NewS3Service())
_, err = s3Client.Upload(&s3manager.UploadInput{
Bucket: aws.String(bucket),
Key: aws.String(
fmt.Sprintf(
"%s/%d/%d/%d",
input.Country,
input.ZipCode,
input.custTime.Year(),
int(input.custTime.Month()))),
Body: *rawData,
})
if err != nil {
return err
}
return nil
}
}
g.Go(s3Upload(&pRmData, pMonthLookupInput))
g.Go(s3Upload(&rmData, input))
g.Go(s3Upload(&nRmData, nMonthLookupInput))
if err := g.Wait(); err == nil {
mPrayer.PreviousMonthData = pMonthPData
mPrayer.CurrentMonthData = prayerData
mPrayer.NextMonthData = nMonthPData
return mPrayer, nil
}
return nil, err
}
Here is my test file.
func TestPrayer(t *testing.T) {
p, err := NewMonthPrayer(
&input,
&S3Store{},
&AladhanStore{},
)
if err != nil {
t.Errorf("error: %s", err)
}
data, err := p.GetMonthPrayers()
if err != nil {
t.Errorf("error: %s", err)
}
t.Logf("Test address: %p", data)
t.Logf("data THIS SHOULDN'T BE NIL: %v", data)
t.Logf("ERROR: %s", err)
}
These are my results. Ignore the pass result, the data is first not nil and second nil.
=== RUN TestPrayer
loop = 0, data= *prayer.PreCurrNextMonthPrayer <nil>
attempting to retrieve prayer data from s3
err= <nil>
monthlyData= 0xc000131180 &{<nil> 0xc0002612f0 0xc00051e780 0xc00011cea0 []}
loop-return: err == nil
return monthlyData address & value = 0xc000131180 &{<nil> 0xc0002612f0 0xc00051e780 0xc00011cea0 []}
post-loop:
monthlyData= 0x0 <nil>
return monthlyData address & value = 0x0 <nil>
prayer_test.go:53: Test address: 0x0
prayer_test.go:55: data THIS SHOULDN'T BE NIL: <nil>
prayer_test.go:56: ERROR: %!s(<nil>)
--- PASS: TestPrayer (0.32s)
PASS
The duplicate was due to the GetMonthPrayer call from NewMonthPrayer, which shouldn't have been the case to begin with. It was called first but returned second, thus overwriting the existing data.
func NewMonthPrayer(input *LookupInput, prayers ...MonthPrayerIface) (*PreCurrNextMonthPrayer, error) {
var err error
t := &PreCurrNextMonthPrayer{
custData: input,
prayers: prayers,
}
t, err = t.GetMonthPrayers()
if err != nil {
return nil, err
}
return t, nil
}
I removed the NewMonthPrayer entirely as it was unnecessary, I also removed the function call in the process, thus fixing the initial problem.
// NewPrayer instantiates a prayer type object with the required input
func NewPrayer(input *LookupInput, prayers ...MonthPrayerIface) *Prayer {
return &Prayer{
custData: input,
prayers: prayers,
}
}

Read and merge two Yaml files in go language

Assuming we have two yaml files
master.yaml
someProperty: "someVaue"
anotherProperty: "anotherValue"
override.yaml
someProperty: "overriddenVaue"
Is it possible to unmarshall, merge, and then write those changes to a file without having to define a struct for every property in the yaml file?
The master file has over 500 properties in it that are not at all important to the service at this point of execution, so ideally I'd be able to just unmarshal into a map, do a merge and write out in yaml again but I'm relatively new to go so wanted some opinions.
I've got some code to read the yaml into an interface but i'm unsure on the best approach to then merge the two.
var masterYaml interface{}
yamlBytes, _ := ioutil.ReadFile("master.yaml")
yaml.Unmarshal(yamlBytes, &masterYaml)
var overrideYaml interface{}
yamlBytes, _ = ioutil.ReadFile("override.yaml")
yaml.Unmarshal(yamlBytes, &overrideYaml)
I've looked into libraries like mergo but i'm not sure if that's the right approach.
I'm hoping that after the master I would be able to write out to file with properties
someProperty: "overriddenVaue"
anotherProperty: "anotherValue"
Assuming that you just want to merge at the top level, you can unmarshal into maps of type map[string]interface{}, as follows:
package main
import (
"io/ioutil"
"gopkg.in/yaml.v2"
)
func main() {
var master map[string]interface{}
bs, err := ioutil.ReadFile("master.yaml")
if err != nil {
panic(err)
}
if err := yaml.Unmarshal(bs, &master); err != nil {
panic(err)
}
var override map[string]interface{}
bs, err = ioutil.ReadFile("override.yaml")
if err != nil {
panic(err)
}
if err := yaml.Unmarshal(bs, &override); err != nil {
panic(err)
}
for k, v := range override {
master[k] = v
}
bs, err = yaml.Marshal(master)
if err != nil {
panic(err)
}
if err := ioutil.WriteFile("merged.yaml", bs, 0644); err != nil {
panic(err)
}
}
For a broader solution (with n input files), you can use this function. I have used #robox answer to do my solution:
func ReadValues(filenames ...string) (string, error) {
if len(filenames) <= 0 {
return "", errors.New("You must provide at least one filename for reading Values")
}
var resultValues map[string]interface{}
for _, filename := range filenames {
var override map[string]interface{}
bs, err := ioutil.ReadFile(filename)
if err != nil {
log.Info(err)
continue
}
if err := yaml.Unmarshal(bs, &override); err != nil {
log.Info(err)
continue
}
//check if is nil. This will only happen for the first filename
if resultValues == nil {
resultValues = override
} else {
for k, v := range override {
resultValues[k] = v
}
}
}
bs, err := yaml.Marshal(resultValues)
if err != nil {
log.Info(err)
return "", err
}
return string(bs), nil
}
So for this example you should call it with this order:
result, _ := ReadValues("master.yaml", "overwrite.yaml")
In the case you have an extra file newFile.yaml, you could also use this function:
result, _ := ReadValues("master.yaml", "overwrite.yaml", "newFile.yaml")
DEEP MERGE TWO YAML FILES
package main
import (
"fmt"
"io/ioutil"
"sigs.k8s.io/yaml"
)
func main() {
// declare two map to hold the yaml content
base := map[string]interface{}{}
currentMap := map[string]interface{}{}
// read one yaml file
data, _ := ioutil.ReadFile("conf.yaml")
if err := yaml.Unmarshal(data, &base); err != nil {
}
// read another yaml file
data1, _ := ioutil.ReadFile("conf1.yaml")
if err := yaml.Unmarshal(data1, &currentMap); err != nil {
}
// merge both yaml data recursively
base = mergeMaps(base, currentMap)
// print merged map
fmt.Println(base)
}
func mergeMaps(a, b map[string]interface{}) map[string]interface{} {
out := make(map[string]interface{}, len(a))
for k, v := range a {
out[k] = v
}
for k, v := range b {
if v, ok := v.(map[string]interface{}); ok {
if bv, ok := out[k]; ok {
if bv, ok := bv.(map[string]interface{}); ok {
out[k] = mergeMaps(bv, v)
continue
}
}
}
out[k] = v
}
return out
}

pass interface pointer and assignment value

I want to write a file cache in Go. I am using gob encoding, and saving to a file, but my get function has some problem:
package main
import (
"encoding/gob"
"fmt"
"os"
)
var (
file = "tmp.txt"
)
type Data struct {
Expire int64
D interface{}
}
type User struct {
Id int
Name string
}
func main() {
user := User{
Id: 1,
Name: "lei",
}
err := set(file, user, 10)
if err != nil {
fmt.Println(err)
return
}
user = User{}
err = get(file, &user)
if err != nil {
fmt.Println(err)
return
}
//user not change.
fmt.Println(user)
}
func set(file string, v interface{}, expire int64) error {
f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer f.Close()
//wrapper data
//save v in data.D
data := Data{
Expire: expire,
D: v,
}
gob.Register(v)
enc := gob.NewEncoder(f)
err = enc.Encode(data)
if err != nil {
return err
}
return nil
}
func get(file string, v interface{}) error {
f, err := os.OpenFile(file, os.O_RDONLY, 0600)
if err != nil {
return err
}
defer f.Close()
var data Data
dec := gob.NewDecoder(f)
err = dec.Decode(&data)
if err != nil {
return err
}
//get v
v = data.D
fmt.Println(v)
return nil
}
The get function passes interface type and I want to change the value, but not change.
http://play.golang.org/p/wV7rBH028o
In order to insert an unknown value into v of type interface{}, you need to use reflection. This is somewhat involved, but if you want to support this in full, you can see how its done by walking through the decoding process in some of the encoding packages (json, gob).
To get you started, here's a basic version of your get function using reflection. This skips a number of checks, and will only decode something that was encoded as a pointer.
func get(file string, v interface{}) error {
f, err := os.OpenFile(file, os.O_RDONLY, 0600)
if err != nil {
return err
}
defer f.Close()
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
panic("need a non nil pointer")
}
var data Data
dec := gob.NewDecoder(f)
err = dec.Decode(&data)
if err != nil {
return err
}
dv := reflect.ValueOf(data.D)
if dv.Kind() != reflect.Ptr {
panic("didn't decode a pointer")
}
rv.Elem().Set(dv.Elem())
return nil
}
I would actually suggest an easier way to handle this in your own code, which is to have the Get function return an interface{}. Since you will know what the possible types are at that point, you can use a type switch to assert the correct value.
An alternative approach is to return directly the value from the file:
func get(file string) (interface{}, error) {
f, err := os.OpenFile(file, os.O_RDONLY, 0600)
if err != nil {
return nil, err
}
defer f.Close()
var data Data
dec := gob.NewDecoder(f)
err = dec.Decode(&data)
if err != nil {
return nil,err
}
fmt.Println(data.D)
return data.D,nil
}
full working example: http://play.golang.org/p/178U_LVC5y

Resources