Pass a string into a function and reference struct

I am curious if there is a way to pass a string into a function and use that string to reference a struct.

The variable have is what the string comes out as variable want is basically what I’d like variable have to do.

I hope that makes sense. Basically I want variable have to not be assigned to string s but to type one struct like want is

https://play.golang.org/p/WtFiCAgOs6J

   package main

import (
	"fmt"
)

type one struct {
    name string
}

func action(s string) {
       have := s
       fmt.Println(have)
       want := one{}
       fmt.Println(want)
}

func main() {
   s := `one{}`
   action(s)
}

It’s totally not clear to me what you want to do exactly. Do you want to select a struct type based on the string value given (i.e., a factory of some kind)? A switch is one way:

var want interface{} // this is a bad smell
switch s {
  case "one":
    want = one{}
  case "two":
    want = two{}
  default:
    panic("wat")
}

You need to figure out an appropriate type for want. The type interface{} that I used above can be used to hold anything, but in return you can do almost nothing with it.

So what’s the purpose of the exercise?

I am sending in json to an API and I’d like to get the response back and use it. At the moment I’d need to move the r := sendRespose{} line to the original function, but I’m wondering if I can work around that.

// SendSMS sends a text with the users phone number
func (c *Client) SendSMS(message string, to ...string) error {
	// Endcoding:(0 => 7-bit, 1 => 8-bit, 2 => UCS2)
	var data = &send{
		Recipients:     to,
		Message:        message,
		Encoding:       0,
		SmsConnectorID: 0,
		Store:          true,
		AuthToken:      c.AuthToken,
		APIKey:         c.APIKey,
	}
	url := EndPointURL + "remote/sms/send"
	req, err := buildIt(data, url)
	if err != nil {
		panic(err)
	}
	fmt.Println("send response:", req)
	// confirmSent(req)
	return nil
}

func buildIt(data interface{}, url string) (sendRespose, error) {
	send, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}
	fmt.Println("send sms", string(send))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(send))
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(reflect.TypeOf(body))
	// //Response status and body for quick testing
	// fmt.Println("Status:", resp.Status)
	// fmt.Println("Body:", string(body))
	r := sendRespose{}
	_ = json.Unmarshal(body, &r)
	fmt.Println(r)
	if r.ErrorCode != 0 {
		return r, ErrorCode{
			time.Now(),
			r.ErrorCode,
		}
	}
	return r, nil
}

You can accept a pointer to the response struct, much like json.Unmarshal itself does.

func whatever() {
  var data = &send{
    ...
  }

  var res sendResponse
  err := buildIt(data, &res, url)
  if err != nil {
    ...
  }
}

func buildIt(data, resp interface{}, url string) error {
  ...
  err := json.Unmarshal(body, &resp)
  ...
}

1 Like

Thanks, that makes sense. I had tried to do something like that but I think I just missed using the pointer.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.