doy51723
doy51723
2018-08-17 02:20

将接口传递给函数

已采纳

I'm trying to write a configuration package that takes a json filename and a configuration struct. It should unmarshal the json into the passed-in struct and return it. I'm trying to work with interfaces so I can pass any struct I want

The error is:

panic: interface conversion: interface {} is map[string]interface {}, not *main.ConfigurationData

I'm not quite sure how to solve this issue.

Here is my main package

package main

import (
    "config"
    "commons"
)

type ConfigurationData struct {
    S3ARN string `json:"S3ARN"`
    SQSQueueUrl string `json:"SQSQueueUrl"`
}

var configData *ConfigurationData

func main(){
    configData=config.Load("aws.config.json",configData).(*ConfigurationData)
    commons.Dump(configData)
}

Here is my config package

package config

import (
    "os"
    "encoding/json"
    "sync"
    "commons"
)

var configLock = new(sync.RWMutex)

func Load(filename string,config interface{})interface{} {
    file, err := os.Open(filename)
    commons.CheckErrorf(err, "Config Open Error")
    defer file.Close()
    decoder := json.NewDecoder(file)
    configLock.Lock()
    err = decoder.Decode(&config)
    commons.CheckErrorf(err, "Config Decode Error")
    configLock.Unlock()
    return config
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dongzhang1864 dongzhang1864 3年前

    This answer explains well why you get the exception.

    What you should do:

    When the encoding/json package runs into a type that implements the Marshaler interface, it uses that type’s MarshalJSON() method instead of the default marshaling code to turn the object into JSON. Similarly, when decoding a JSON object it will test to see if the object implements the Unmarshaler interface, and if so it will use the UnmarshalJSON() method instead of the default unmarshaling behavior.

    Mine solution for this would be to implement UnmarshalJSON method on *ConfigurationData and method Load should accept Unmarshaler interface instead of interface{}.

    You can read more about technics here: https://blog.gopheracademy.com/advent-2016/advanced-encoding-decoding/

    Then you simple would do json.Unmarshal(b, &config) inside the Load method where b is []byte read from file.

    点赞 评论 复制链接分享
  • doudui9516 doudui9516 3年前

    According to the documentation on json.Unmarshall unmarshalling into an interface value will unmarshall to a new struct of one of a predefined list of types:

    To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:

    bool, for JSON booleans 
    float64, for JSON numbers
    string, for JSON
    strings []interface{}, for JSON arrays 
    map[string]interface{}, for JSON objects
    nil for JSON null
    

    In your case, the type that was chosen was map[string]interface{}. Within your function, a pointer to that newly unmarshalled struct is stored in the config parameter and returned. The panic occurs as the type of the value returned is not the type you're asserting it is.

    点赞 评论 复制链接分享

为你推荐