Home  >  Article  >  Backend Development  >  Go - Convert pointer to struct slice to interface slice

Go - Convert pointer to struct slice to interface slice

WBOY
WBOYforward
2024-02-09 14:57:081101browse

Go - 将指向结构切片的指针转换为接口切片

php Editor Baicao In the Go programming language, sometimes we need to convert pointers to structure slices into interface slices. This conversion is very useful in some specific situations, such as when we need to modify elements in a slice. By converting pointers into interface slices, we can easily access and modify elements in the slice without worrying about data consistency and synchronization issues. In this article, we'll explain how to make this conversion and provide some examples of practical applications.

Question content

I cut out some production GoLang code to create the following example:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    var aData []AlphaStruct
    var bData []BetaStruct

    readData(&aData)
    readData(&bData)

    // Do other stuff with the loaded structures.
}

func readData(structSlicePointer any) {
    json.Unmarshal([]byte(
        "["+
            "{\"name\": \"John Smith\"},"+
            "{\"name\": \"Jane Doe\"}"+
            "]"),
        structSlicePointer)

    var initializers []Initializer

    // At this point I want to do:
    // initializers = structSlicePointer
    // However I can't find any type declarations or casts that will work with the rest of the code.

    for _, initializer := range initializers {
        initializer.Initialize()
    }
}

type Initializer interface {
    Initialize()
}

type AlphaStruct struct {
    Name string `json:"name"`
}

type BetaStruct struct {
    Name string `json:"name"`
}

func (es *AlphaStruct) Initialize() {
    fmt.Printf("In Alpha: %s\n", es.Name)
}

func (es *BetaStruct) Initialize() {
    fmt.Printf("In Beta: %s\n", es.Name)
}

I have many structs and they all implement the same interface.

The idea is that after deserializing them (from JSON) I want to call a method on each loaded object to complete the object initialization. Some JSON files have top-level arrays - i.e. once deserialized, they are lists/slices of structures.

However, I can't find any combination of declarations that would allow me to do the following simultaneously:

  • Execution json.Unmarshal()
  • Iterate over each loaded structure and call methods.

Obviously, I can split this into two functions (loadData and initializeData) to execute these two functions.

Is there any way to restructure this so that it works as a single method?

Workaround

You can declare the method as a generic method that accepts a slice of a member structure that implements the Initializer interface.

To do this, you can declare your method like this:

func readData[T Initializer](structSlicePointer *[]T) {
    json.Unmarshal(
        []byte("[{\"name\": \"John Smith\"},{\"name\": \"Jane Doe\"}]"),
        structSlicePointer,
    )
    for _, initializer := range *structSlicePointer {
        initializer.Initialize()
    }
}

Note that this will require you to declare the slice value as a pointer for use with pointer receiver methods on the structure (e.g. []*AlphaStruct vs. []AlphaStruct ):

func main() {
    var aData []*AlphaStruct
    var bData []*BetaStruct

    readData(&aData)
    readData(&bData)
}

Output:

In Alpha: John Smith
In Alpha: Jane Doe
In Beta: John Smith
In Beta: Jane Doe

The above is the detailed content of Go - Convert pointer to struct slice to interface slice. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete