Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to convert known type to pointer to type parameter in a switch?

I’m trying to write a function which converts a byte array of JSON string to another in accordance with the type parameter of the return value as the following rule:

  • map[string]interface{}: convert to map[string]interface{}
  • []byte: no conversion, return as is
  • struct: convert to the struc

My code is as follow:

func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
    var buff T

    switch any(result).(type) { // https://appliedgo.com/blog/a-tip-and-a-trick-when-working-with-generics
    case *[]byte:
        result = &T(jsonByteArray)
    default:
        err = json.Unmarshal(jsonByteArray, &buff)
        result = &buff
    }

    return
}

This code occurs following type error at the point of cast the type of jsonByteArray to T as follows:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

cannot convert jsonByteArray (variable of type []byte) to type T

How can I assign the pointer of this []byte type variable to the generic type return value?

>Solution :

Since T is constrained by any, you can’t directly convert. You have to assert that &jsonByteArray is really the same type as *T in that switch case:

func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
    var buff T

    switch any(result).(type) {
    case *[]byte:
        result = any(&jsonByteArray).(*T)
    default:
        err = json.Unmarshal(jsonByteArray, &buff)
        result = &buff
    }

    return
}

This makes the compile error go away, however it isn’t particularly good design. If you need to specialize json.Unmarshal for only one type (*[]byte) you are better off changing the call sites instead of using a generic function.

I assume that your goal is to allow callers to get the byte slice as is, instead of unmarshalling. Then at call site you would call the function as

data := GetJsonData[[]byte](jsonByteArray)

This means that at that point you already know that jsonByteArray is a byte slice.

Then, there’s no reason to call the function. You can simply take the address of the argument: data := &jsonByteArray, and use json.Unmarshal everywhere else.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading