Interface UI Pointer and Destination Value

I want to write a cache file in Go. I use gob encoding and save to file, but my function gethas some problems:

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 function getpasses the type of interface, and I want to change the value, but not change it. http://play.golang.org/p/wV7rBH028o

+4
source share
2 answers

An alternative approach is to directly return 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

+1
source

v interface{}, . , , , , (json, gob).

, get, . , .

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
}

, get interface{}. , , .

+2

Source: https://habr.com/ru/post/1546718/


All Articles