gpt4 book ai didi

go - 对项目集合执行操作

转载 作者:数据小太阳 更新时间:2023-10-29 03:15:21 25 4
gpt4 key购买 nike

在我的实际代码中,我正在使用 encoding/xml 解析一个 XML 文档,我基本上有一堆如下形式的嵌套结构——所有这些都可能出现多次,除了顶级 statements 元素:

statements
statement
opcode
args
pre
post

我是 Go 的新手,我显然误解了 interface{}(空接口(interface))的工作原理:

.\stmtgen.go:58: cannot use print_name (type func(Statement)) as type func(interface {}) in argument to performAction
.\stmtgen.go:58: cannot use slist (type []Statement) as type []interface {} in argument to performAction

相关示例代码:

package main
import "fmt"

// Actually a structure in my code, but this suffices for demonstration.
type Opcode int

// A Statement has a Name and multiple Opcodes may use this Name.
type Statement struct {
Name string
Opcodes []Opcode
}

// Print the statement name.
func print_name(stmt Statement) {
fmt.Println(stmt.Name)
}

// Perform an action on each item of a collection.
func performAction(action func(interface{}), v []interface{}) {
for i := range v {
action(v[i])
}
}

func main() {
slist := make([]Statement, 3)
slist[0] = Statement{"Statement 1"}
slist[1] = Statement{"Statement 2"}
slist[2] = Statement{"Statement 3"}

//ERROR HERE
performAction(print_name, slist)
}

我必须创建函数来打印每种类型的值吗?

最佳答案

一个空的 interface{} 可以包含任何值并作为 interface{} 类型传递。当你需要它的值时,你可以像这样执行类型断言:

var anyValue interface{}
anyValue = "hello"

strValue := anyValue.(string)

如果 anyValue 不是被断言的类型,那么它将导致 panic

如果接口(interface)是具有多重返回的类型,则类型断言也可用于返回 bool

strValue, ok := anyValue.(string)
if ok {
//anyValue contains a string!
}

如果你不知道接口(interface)的类型,你可以像这样使用一个开关来确定它的类型:

switch val := anyValue.(type) {
case string:
// anyValue contains a string
// and val is a string
break
case int:
// anyValue contains an int
// and val is and int
break
default:
//unhandled interface type
}

希望这能让空接口(interface){}类型更清晰。

interfaces{...} 其中声明了方法是不同的,它们不能有成员(就像结构可以),只有方法,并且它们的底层类型必须实现接口(interface)中声明的所有方法。你可以有一个接口(interface) actionPerformer(接口(interface)名称应该有后缀“er”,因为它们正在做某事)

type actionPerformer interface {
action(interface{})
}

可以将实现接口(interface)中所有方法的类型强制转换为该接口(interface)类型,然后如果您在接口(interface)上调用这些方法之一,它将在基础类型上运行该方法。例如,如果 Statement 结构实现了 action(interface{}) 方法,则 Statement 结构可以转换为 actionPerformer 类型,如果 action(interface {}) 函数在 actionPerformer 上被调用,Statement 结构上的 Action 函数被运行。因此,您可以拥有多种类型,它们都具有 action(interface{}) 方法,并且它们都可以转换为 actionPerformer,您可以在其上调用操作函数。

func (code Opcode) action(arg interface{}) {
fmt.Println(arg.(int) + int(code))
}

func (stmt Statement) action(arg interface{}) {
fmt.Println(arg.(string), stmt.Name)
}

stmt := Statement{"Statement 1", nil}
stmtActionPerformer := actionPerformer(stmt)

opcode := Opcode(5)
opcodeActionPerformer := actionPerformer(opcode)

stmtActionPerformer.action("hello") // will print "hello "+whatever the statements name is
opcodeActionPerformer.action(2) //will print be 7

类型断言仍然可以用在这些类型的接口(interface)上,例如

stmt := stmtActionPerformer.(Statement)
fmt.Println(stmt.Name)

这是一个人为的示例,但考虑到这一点,您可能希望使用这样的接口(interface)编写代码。请记住,接口(interface)之间的转换成本很高,因此应谨慎进行,但如果使用得当,它们是一个强大的工具。

对于您的示例,一个简单的 printNames 函数将比所有接口(interface)转换更有效(请注意,在 golang 中,名称应采用 CamelCase 格式,而不是使用下划线)

func printNames(stmts []Statement) {
for _, stmt := range stmts {
fmt.Println(stmt.Name)
}
}

拥有一个类型 StatementList 并向其添加方法可能也很有用:

type StatementList []Statement

func (list StatementList) printNames() {
for _, stmt := range list {
fmt.Println(stmt.Name)
}
}

掌握这些东西会让 golang 变得更加有趣,希望这对您有所帮助:)

关于go - 对项目集合执行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36880335/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com