3 回答

TA貢獻1817條經驗 獲得超14個贊
這個問題很難回答,因為你有點忘了以明確的方式問一個問題,所以我將根據你寫的內容提取一個問題來開始我的回答。我相信我們可以這樣做:
問題陳述
[...]我的困惑是如何創建一個configmanager類對象以及我應該如何在我第一次調用時初始化我的所有配置,configmanager并且還可以使用一些 getter 訪問ClientMetricsstruct
我相信這里真正的問題是“我如何將讀取和解組文件的關注與存儲結果以供我的程序使用的關注區分開來?”。
通過將事物分解為多個函數/方法來分離關注點是很常見的,您已經在某種程度上做到了這一點。然而,存儲嚴格來說是類型的問題,所以我們需要一種能夠保存結果的類型。我將利用這個機會Manager從類型名稱中省略這個詞,因為它所做的只是提供無用的抽象。這種類型不管理配置。它是配置,因為它包含所有配置。
type Config struct {
ClientMapConfigs []ClientMapConfig
DataMapConfigs []DataMapConfig
ProcessDataConfigs []ProcessDataConfig
}
請注意,這些字段以大寫字母開頭,使其公開。這表明其中可能存在廢話,因為沒有任何內容可以防止寫入,這與我們從文件中讀取這些數據的事實一致。正確的程序必須在使用之前驗證這些數據。然后,您可以在變量名稱中傳達已驗證數據的有效性。
func main() {
validConfig := getValidConfig("path/to/dir")
// ...
}
func getValidConfig(configDirectoryPath string) *Config {
config, err := NewConfigFromConfigDirectory(configDirectoryPath)
if err != nil {
log.Printf("Failed to read config from dir '%s': %v\n", configDirectoryPath, err)
os.Exit(1)
}
if err = ValidateConfig(config); err != nil {
log.Printf("Config from dir '%s' failed to validate: %v\n", configDirectoryPath, err)
os.Exit(1)
}
}
func NewConfigFromConfigDirectory(configDirectoryPath string) *Config {
// <- read individual configs and add to slices here
return &Config{ // This is the closest to a "constructor" that Go has.
ClientMapConfigs: clientMapConfigs,
DataMapConfigs: dataMapConfigs,
ProcessDataConfigs: processDataConfigs,
}
}
請注意,驗證和讀取配置的函數不需要接收器,即成為結構的方法。它們可以作為獨立功能使用,直到您的需求發生變化,需要為任一邏輯引入狀態性。
此外,我在這里對錯誤情況使用退出代碼1,因為 Golang2在程序因恐慌而終止時使用代碼。前者可以被認為是環境問題,而后者則表明程序本身存在問題。這是一個有用的區別,并且與您可能從 Java 中知道的語義Exception相一致。RuntimeException

TA貢獻1827條經驗 獲得超4個贊
我認為問題在于您從 Java/C# 的角度看待 Go,因此難以理解這些特性。如果您有時間,那么我建議您在開始編碼之前先閱讀一些 Go 教程或書籍(這個非常好:https ://www.amazon.com/Programming-Language-Addison-Wesley-Professional-計算/dp/0134190440 )
要直接回答您的問題,您需要做的是創建一個函數,該函數返回指向結構對象的指針(請參見此處的簡單示例:https ://gobyexample.com/structs )
以 ClientMetric 為例:
func NewClientMetric(ClientID int, CustomerData CustomerData, LegCustomer []int, OtherIds []int, CatID int) (*ClientMetric, error) {
//validate your inputs
//in case of errors, create and error message in the variable err and then: return nil, err
//other code which would go into a typical constructor would go here
return &ClientMetric{ClientID,CustomerData, LegCustomer, OtherIds, CatID}, nil
}
在這種情況下,該函數NewClientMetric是構造函數,它返回一個指向新創建對象的指針/引用。它還返回一個錯誤對象,這和說構造函數拋出異常是一樣的。正如您需要在 Java 中使用 try/catch 一樣,您需要檢查以處理此函數返回的 err 變量。
您需要為每種類型創建類似的功能。
至于 getter 和 setter,一般來說,在 Go 中應該避免這種情況。您可以直接訪問結構的屬性。僅當您要在返回屬性之前對屬性執行某些操作時,函數(如 getter)才有用。像這樣的東西:
type Customer struct {
FirstName string
LastName string
}
func (this *Customer) GetFullName() string {
return this.FirstName + " " + this.LastName
}
然后可以像這樣訪問這些:
var customer *Customer
customer = &Customer{"John","Smith")
fmt.Println(customer.FirstName)
fmt.Println(customer.LastName)
fmt.Println(customer.GetFullName())
請注意,以大寫字母開頭的屬性、函數和方法是公共的,其他的是私有的。如果FirstName寫為firstName,則在聲明它的包之外將無法訪問它。
請注意,如果指針為 null/nil,我不會檢查錯誤,但始終建議這樣做。

TA貢獻1802條經驗 獲得超4個贊
我可以說 10 個不同的配置(文件),每個配置都可以有自己的結構,因為它是不同的配置,所以我需要為它們有單獨的結構
這看起來像動態 JSON 結構解組,這是由John Asmuth在2015 年在使用混合結構進行解碼時提出的
您可以在此處運行以下示例。
type Dog struct {
Name string
Frisbees int
}
type Cat struct {
Name string
Strings int
}
type RawAnimal struct {
Type string
Cat
Dog
}
type Animal RawAnimal
func (a *Animal) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, (*RawAnimal)(a)); err != nil {
return err
}
switch a.Type {
case "cat":
return json.Unmarshal(data, &a.Cat)
case "dog":
return json.Unmarshal(data, &a.Dog)
}
return fmt.Errorf("unknown type %q", a.Type)
}
從那里,您的 ConfigManager 將根據讀取的原始 JSON 實例化正確的 Config 結構。
- 3 回答
- 0 關注
- 172 瀏覽
添加回答
舉報