Golang中如何为结构体填充值

Golang中如何为结构体填充值 各位, 我有以下结构体并想要填充值,运行时出现错误,可能是我的值设置不正确

package main
import (
 "fmt"
 "os"
 "strings"
 "bufio"
)

func main() {
// 创建可多次调用的单个读取器
reader := bufio.NewReader(os.Stdin)
// 提示并读取
fmt.Print("输入 BIG-IP 管理 IP: ")
bigip_mgmt, _ := reader.ReadString('\n')
fmt.Print("输入 BIG-IP 用户名: ")
user, _ := reader.ReadString('\n')
fmt.Print("输入 BIG-IP 密码: ")
pass, _ := reader.ReadString('\n')
fmt.Print("输入 BIG-IP IPFIX 池: ")
Ipfix_pool, _ := reader.ReadString('\n')

// 去除空白字符并打印
fmt.Printf("Bigip 管理 IP: \"%s\", Bigip 用户名: \"%s\", Bigip 密码: \"%s\", Bigip IPFIX 池 \"%s\"\n",
  strings.TrimSpace(bigip_mgmt), strings.TrimSpace(user), strings.TrimSpace(pass), strings.TrimSpace(ipfix_pool))
fmt.Printf(bigip_mgmt)
 create := createipfx()
 fmt.Println(create)
}
func createipfx() string {
  type Payload struct {
  	Name    string `json:"name"`
  	Monitor string `json:"monitor"`
  	Members []struct {
  		Name    string `json:"name"`
  		Address string `json:"address"`
  	} `json:"members"`
  }
  data := Payload{
  // 填充结构体
   Name: "FirstIPFIXPool",
   Monitor: "gateway_icmp ",
   Members: Members[]{
     {
     Name: Ipfix_pool:4739,
     Address: Ipfix_pool,
   },
   },
  }
  fmt.Println(data)
  payloadBytes, err := json.Marshal(data)
  if err != nil {
  	// 处理错误
  }
  body := bytes.NewReader(payloadBytes)

  req, err := http.NewRequest("POST", os.ExpandEnv("https://bigip_mgmt/mgmt/tm/ltm/pool"), body)
  if err != nil {
  	// 处理错误
  }
  req.SetBasicAuth(user, pass)
  req.Header.Set("Content-Type", "application/json")

  resp, err := http.DefaultClient.Do(req)
  if err != nil {
  	// 处理错误
  }
  defer resp.Body.Close()
  return "创建了 ipfix 池"

}

运行时出现语法错误,可能是我的 Go 结构体值设置不正确

运行 ipfix_deploy.go

./ipfix_deploy.go:43:21: 语法错误:意外的 ],期望表达式
./ipfix_deploy.go:44:6: 语法错误:意外的 {,期望表达式
./ipfix_deploy.go:45:6: 语法错误:意外的 Name,期望 ]
./ipfix_deploy.go:48:4: 语法错误:意外的 },期望表达式
./ipfix_deploy.go:49:3: 语法错误:意外的 },期望表达式

更多关于Golang中如何为结构体填充值的实战教程也可以访问 https://www.itying.com/category-94-b0.html

14 回复
@NobbZ 有效了!!非常感谢

更多关于Golang中如何为结构体填充值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在我看来,为那个字段提取一个合适的类型比使用匿名结构体更简单。

请使用论坛的代码格式化功能,或者更好的做法是将你的示例发布到 play.golang.org

是的,这就是为什么我在将代码粘贴到 Playground 时,会仔细阅读错误信息。我已经这样做过很多次了,所以已经习惯了替换那些被弄乱的引号。

scshitole:

Ipfix_pool, _ := reader.ReadString('\n')

你应该使用双引号,但这可能只是其中一个错误。

Ipfix_pool, _ := reader.ReadString('\n')

能否请您帮个忙,用三个反引号将代码正确格式化,采用Markdown风格的围栏式代码块?

这样会使代码更易于阅读,尤其是便于复制,因为引号将保持正确的引号格式。

我拒绝再次修复这些问题……

已完成,我认为在以下代码处出现了复合字面量缺少类型的错误:

   Members: {
     {
       Name:    "Ipfix_pool:4739",
       Address: "Ipfix_pool",
     },
   },

请仔细查看我是如何修复这个问题的。你需要从外围结构中复制匿名结构体的声明。

		Members: []struct {
			Name    string `json:"name"`
			Address string `json:"address"`
		}{
			{
				Name:    "Ipfix_pool:4739",
				Address: "Ipfix_pool",
			},
		},

你还在运行playground上的相同代码吗?

那个只有// handle error here注释的代码?请用适当的错误处理替换这些注释,创建一个包含正确代码的playground或gist。但也许当你引入错误处理时,你就会发现问题,因为我猜你没有正确设置连接或无法连接到主机之类的情况。

// handle error here

NobbZ:

不,使用 \n 没问题。ReadString 接收一个字节作为参数,虽然 rune 类型可以强制转换为字节,但字符串类型不行,所以这里需要使用单引号。

我将这段代码复制到 Playground 后报错了,但现在发现帖子中的普通单引号实际上被替换成了其他类型的引号(’ 和 ')😄 而且我完全没有查看函数签名。

@NobbZ 谢谢,但是在我输入所有值后现在出现了运行时panic错误

SJC-ML-SHITOLE:tetration shitole$ go run ipfix_deploy.go
Enter BIG-IP Management IP: 10.192.74.73
Enter username for BIG-IP: admin
Enter password  for BIG-IP: admin
Enter IPFIX Pool  for BIG-IP: 15.1.1.1
Bigip Management is: "10.192.74.73", Bigip username : "admin", Bigip pass : "admin", Bigip IPFIX Pool "15.1.1.1"
10.192.74.73
value of data {Name:FirstIPFIXPool Monitor:gateway_icmp  Members:[{Name:Ipfix_pool:4739 Address:Ipfix_pool}]}panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x11fc67d]

goroutine 1 [running]:
main.createipfx(0x0, 0x0)
	/Users/shitole/tetration/ipfix_deploy.go:75 +0x38d
main.main()
	/Users/shitole/tetration/ipfix_deploy.go:30 +0x58e
exit status 2

不,'\n' 没问题。ReadString 接受一个 byte 作为参数,rune 可以强制转换为 byte,但字符串不行,所以这里使用单引号。

我猜这与第 42 行的 Members: Members[]{...} 有关。

  1. Members 不是一个已定义的结构体。
  2. Members(结构体字段)接受一个 []struct{…}

在我用以下代码修复之后:

Members: []struct {
Name string `json:"name"`
Address string `json:"address"`
}{
{
Name: "Ipfix_pool:4739",
Address: "Ipfix_pool",
},
},

由于第 24 行未定义 ipfix_pool,我确实遇到了另一个错误。通过简单地将 ipfix_pool 重命名为 Ipfix_pool 来修复它,然后导致了下一个错误:

prog.go:53:22: undefined: json
prog.go:57:9: undefined: bytes
prog.go:59:13: undefined: http
prog.go:63:18: undefined: user
prog.go:63:24: undefined: pass
prog.go:66:14: undefined: http

我可以通过添加到 import 语句 来修复大部分错误:

import (
  ...
  "encoding/json"
  "bytes"
  "net/http"
)

但仍然剩下这两个错误:

prog.go:66:18: undefined: user
prog.go:66:24: undefined: pass

我不会深入探讨这个问题。我把这些留给原帖作者。

PS:这是我在 Playground 上的当前结果链接:https://play.golang.org/p/zSNoyD_DsGa

感谢您的建议,我已经进行了修改,但现在出现了这个错误:prog.go:46:12: 复合字面量中缺少类型

package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strings"
)

func main() {
	// 创建一个可多次调用的读取器
	reader := bufio.NewReader(os.Stdin)
	// 提示并读取输入
	fmt.Print("输入 BIG-IP 管理 IP: ")
	bigip_mgmt, _ := reader.ReadString('\n')
	fmt.Print("输入 BIG-IP 用户名: ")
	user, _ := reader.ReadString('\n')
	fmt.Print("输入 BIG-IP 密码: ")
	pass, _ := reader.ReadString('\n')
	fmt.Print("输入 BIG-IP IPFIX 池: ")
	Ipfix_pool, _ := reader.ReadString('\n')

	// 去除空白字符并打印
	fmt.Printf("Bigip 管理 IP: \"%s\", Bigip 用户名: \"%s\", Bigip 密码: \"%s\", Bigip IPFIX 池 \"%s\"\n",
		strings.TrimSpace(bigip_mgmt), strings.TrimSpace(user), strings.TrimSpace(pass), strings.TrimSpace(Ipfix_pool))
	fmt.Printf(bigip_mgmt)
	create := createipfx()
	fmt.Println(create)
}

func createipfx() string {
	type Payload struct {
		Name    string `json:"name"`
		Monitor string `json:"monitor"`
		Members []struct {
			Name    string `json:"name"`
			Address string `json:"address"`
		} `json:"members"`
	}
	data := Payload{
		// 填充结构体
		Name:    "FirstIPFIXPool",
		Monitor: "gateway_icmp ",
		Members: {
			{
				Name:    "Ipfix_pool:4739",
				Address: "Ipfix_pool",
			},
		},
	}
	fmt.Println(data)
	payloadBytes, err := json.Marshal(data)
	if err != nil {
		// 处理错误
	}
	body := bytes.NewReader(payloadBytes)

	req, err := http.NewRequest("POST", os.ExpandEnv("https://bigip_mgmt/mgmt/tm/ltm/pool"), body)
	if err != nil {
		// 处理错误
	}
	req.SetBasicAuth("user", "pass")
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		// 处理错误
	}
	defer resp.Body.Close()
	return "已创建 ipfix 池"

}

在您的代码中,结构体填充存在几个语法错误。主要问题在于结构体成员初始化的写法不正确。以下是修正后的代码:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strings"
    "bufio"
)

// 将变量声明为包级变量,以便在函数间共享
var (
    bigip_mgmt string
    user       string
    pass       string
    Ipfix_pool string
)

func main() {
    // 创建可多次调用的单个读取器
    reader := bufio.NewReader(os.Stdin)
    
    // 提示并读取
    fmt.Print("输入 BIG-IP 管理 IP: ")
    bigip_mgmt, _ = reader.ReadString('\n')
    fmt.Print("输入 BIG-IP 用户名: ")
    user, _ = reader.ReadString('\n')
    fmt.Print("输入 BIG-IP 密码: ")
    pass, _ = reader.ReadString('\n')
    fmt.Print("输入 BIG-IP IPFIX 池: ")
    Ipfix_pool, _ = reader.ReadString('\n')

    // 去除空白字符并打印
    fmt.Printf("Bigip 管理 IP: \"%s\", Bigip 用户名: \"%s\", Bigip 密码: \"%s\", Bigip IPFIX 池 \"%s\"\n",
        strings.TrimSpace(bigip_mgmt), strings.TrimSpace(user), strings.TrimSpace(pass), strings.TrimSpace(Ipfix_pool))
    
    create := createipfx()
    fmt.Println(create)
}

func createipfx() string {
    type Payload struct {
        Name    string `json:"name"`
        Monitor string `json:"monitor"`
        Members []struct {
            Name    string `json:"name"`
            Address string `json:"address"`
        } `json:"members"`
    }

    // 修正结构体填充
    data := Payload{
        Name:    "FirstIPFIXPool",
        Monitor: "gateway_icmp",
        Members: []struct {
            Name    string `json:"name"`
            Address string `json:"address"`
        }{
            {
                Name:    fmt.Sprintf("%s:4739", strings.TrimSpace(Ipfix_pool)),
                Address: strings.TrimSpace(Ipfix_pool),
            },
        },
    }

    fmt.Printf("%+v\n", data)
    
    payloadBytes, err := json.Marshal(data)
    if err != nil {
        return fmt.Sprintf("JSON 序列化错误: %v", err)
    }
    
    body := bytes.NewReader(payloadBytes)

    // 使用正确的 URL 构建
    url := fmt.Sprintf("https://%s/mgmt/tm/ltm/pool", strings.TrimSpace(bigip_mgmt))
    req, err := http.NewRequest("POST", url, body)
    if err != nil {
        return fmt.Sprintf("创建请求错误: %v", err)
    }
    
    req.SetBasicAuth(strings.TrimSpace(user), strings.TrimSpace(pass))
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return fmt.Sprintf("HTTP 请求错误: %v", err)
    }
    defer resp.Body.Close()
    
    return "创建了 ipfix 池"
}

主要修正点:

  1. 结构体切片初始化:将 Members: Members[]{...} 修正为 Members: []struct{...}{...}

  2. 成员字段赋值:修正了 Name: Ipfix_pool:4739 的语法错误,使用 fmt.Sprintf 来构建字符串

  3. 变量作用域:将输入变量声明为包级变量,使其在 createipfx 函数中可用

  4. 字符串处理:添加了 strings.TrimSpace() 来清理输入字符串中的换行符

  5. URL 构建:修正了 URL 构建方式,使用正确的字符串格式化

  6. 错误处理:为 JSON 序列化和 HTTP 请求添加了基本的错误处理

这些修正解决了您遇到的语法错误,并确保结构体能够正确填充和序列化。

回到顶部