Golang中如何将字符串传入函数并引用结构体

Golang中如何将字符串传入函数并引用结构体 我想知道是否有一种方法可以将字符串传递到函数中,并使用该字符串来引用结构体。

变量 have 是字符串的输出形式,而变量 want 基本上是我希望变量 have 能够实现的效果。

我希望这能说得通。基本上,我希望变量 have 不是被赋值为字符串 s,而是像 want 那样被赋值为 type one struct

链接到代码示例

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)
}

更多关于Golang中如何将字符串传入函数并引用结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

谢谢,这样解释就明白了。我之前尝试过类似的方法,但可能漏掉了使用指针这个关键点。

更多关于Golang中如何将字符串传入函数并引用结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


您可以接受指向响应结构体的指针,就像 json.Unmarshal 本身所做的那样。

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)
  ...
}

我不太清楚你到底想做什么。你是想根据给定的字符串值选择结构体类型(即某种工厂模式)吗?使用 switch 语句是一种方法:

var want interface{} // 这不太对劲
switch s {
  case "one":
    want = one{}
  case "two":
    want = two{}
  default:
    panic("wat")
}

你需要为 want 确定一个合适的类型。我上面使用的 interface{} 类型可以用来容纳任何内容,但反过来你几乎无法对它进行任何操作。

所以这个练习的目的是什么?

我正在向API发送JSON数据,希望能获取返回的响应并加以使用。目前我需要将r := sendRespose{}这行代码移到原始函数中,但我想知道是否有其他解决方案。

// SendSMS 使用用户手机号发送短信
func (c *Client) SendSMS(message string, to ...string) error {
	// 编码方式:(0 => 7位, 1 => 8位, 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("发送响应:", 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("发送短信", 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))
	// //用于快速测试的响应状态和响应体
	// fmt.Println("状态:", resp.Status)
	// fmt.Println("响应体:", 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
}

在Go语言中,无法直接将字符串作为代码来引用结构体类型或变量。字符串是数据,而结构体类型是编译时的类型信息。不过,可以通过几种方式实现类似的功能,具体取决于你的需求。以下是两种常见的方法:

方法1:使用映射(map)将字符串映射到结构体实例

通过创建一个映射,将字符串键关联到对应的结构体实例或构造函数。这样,你可以根据字符串选择并操作特定的结构体。

示例代码:

package main

import (
	"fmt"
)

type one struct {
	name string
}

type two struct {
	value int
}

// 定义一个映射,将字符串映射到对应的结构体实例创建函数
var typeMap = map[string]interface{}{
	"one": func() interface{} { return one{name: "default"} },
	"two": func() interface{} { return two{value: 42} },
}

func action(s string) {
	if constructor, exists := typeMap[s]; exists {
		// 通过类型断言获取具体结构体实例
		instance := constructor.(func() interface{})()
		switch v := instance.(type) {
		case one:
			fmt.Printf("have: %+v\n", v)
		case two:
			fmt.Printf("have: %+v\n", v)
		default:
			fmt.Println("unknown type")
		}
	} else {
		fmt.Println("type not found")
	}
}

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

方法2:使用反射(reflect)根据字符串动态创建结构体

如果字符串代表结构体类型名称,可以使用反射包(reflect)来动态创建对应类型的实例。这种方法更灵活,但性能较低且类型安全较弱。

示例代码:

package main

import (
	"fmt"
	"reflect"
)

type one struct {
	name string
}

type two struct {
	value int
}

func action(s string) {
	// 根据字符串获取类型
	var t reflect.Type
	switch s {
	case "one":
		t = reflect.TypeOf(one{})
	case "two":
		t = reflect.TypeOf(two{})
	default:
		fmt.Println("unknown type")
		return
	}
	
	// 创建该类型的实例
	instance := reflect.New(t).Elem().Interface()
	fmt.Printf("have: %+v\n", instance)
}

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

在第一个示例中,输出为:

have: {name:default}

在第二个示例中,输出为:

have: {name:}

根据你的具体场景选择合适的方法。如果结构体类型是固定的,推荐使用映射方法;如果需要动态处理未知类型,反射方法更合适。

回到顶部