zeromicro / go-zero

A cloud-native Go microservices framework with cli tool for productivity.
https://go-zero.dev
MIT License
29.14k stars 3.94k forks source link

Unable to load configs into custom types #4431

Open wjiec opened 1 day ago

wjiec commented 1 day ago

Describe the bug Unable to load configs with custom types and as well as custom UnmarshalYAML implementations.

To Reproduce

  1. The code is
    
    //
    // internal/config/config.go
    //
    type Config struct {
    rest.RestConf
    Schedule DurationOrCronSpec
    }

type DurationOrCronSpec struct { dur time.Duration spec string }

func (d DurationOrCronSpec) UnmarshalYAML(value yaml.Node) error { if value.Kind != yaml.ScalarNode { return fmt.Errorf("pipeline must contain YAML scalar, has %v", value.Kind) }

if err := value.Decode(&d.dur); err != nil {
    return value.Decode(&d.spec)
}
return nil

}

```yaml
//
// etc/greet.yaml
//
Name: ping
Host: 127.0.0.1
Port: 8888
Log:
  Encoding: plain
Schedule: 20m
  1. The error is

    2024/10/21 09:19:39 error: config file etc/greet.yaml, type mismatch for field "Schedule"

Expected behavior Load configuration files correctly

Environments (please complete the following information):

More description I think that's enough.

kesonan commented 1 day ago

Obviously, you declared a structure, but the yaml file contains a string. The types do not match.

wjiec commented 14 hours ago

@kesonan Thanks for the quick reply, as you can see, in order to convert the string type to the struct type I need, I implemented a unmarshaler to enable custom unmarshal of the string. But from the code it looks like go-zero first deserializes the YAML data into a map[string]any object and then tries to assign from the map object to the corresponding Config structure, which obviously loses support for yaml.Unmarshaler.