英文:
How can I pass a struct to a function as parameter?
问题
如何在golang中将结构体作为参数传递给函数?这是我的代码:
package main
import (
"fmt"
)
type MyClass struct {
Name string
}
func test(class interface{}) {
fmt.Println(class.(MyClass).Name)
}
func main() {
test(MyClass{Name: "Jhon"})
}
当我运行它时,我得到了以下错误:
# command-line-arguments
/tmp/sandbox290239038/main.go:12: class.Name undefined (type interface {} has no field or method Name)
这是play.golang.org的链接:fiddle。
英文:
How can I pass a struct to function as a parameter in golang? There is my code:
package main
import (
"fmt"
)
type MyClass struct {
Name string
}
func test(class interface{}) {
fmt.Println(class.Name)
}
func main() {
test(MyClass{Name: "Jhon"})
}
when I run it, I am getting an error like this
# command-line-arguments
/tmp/sandbox290239038/main.go:12: class.Name undefined (type interface {} has no field or method Name)
there is play.golang.org fiddle address.
答案1
得分: 48
你正在寻找的是:
func test(class MyClass) {
fmt.Println(class.Name)
}
目前这个方法将class
识别为实现了空接口的某个对象(这意味着在该作用域中,它的字段和方法是完全未知的),这就是为什么你会得到错误。
你的另一个选择是这样的:
func test(class interface{}) {
if c, ok := class.(MyClass); ok { // 对其进行类型断言
fmt.Println(c.Name)
}
}
但在你的示例中没有必要这样做。只有在你要进行类型切换或者根据class
的实际类型执行不同的代码路径时才有意义。
英文:
You're looking for;
func test(class MyClass) {
fmt.Println(class.Name)
}
As it stands the method recognizes class
as some object which implements the empty interface (meaning in that scope it's fields and methods are completely unknown) which is why you get the error.
Your other option is something like this;
func test(class interface{}) {
if c, ok := class.(MyClass); ok { // type assert on it
fmt.Println(c.Name)
}
}
But there is no reason to in your example. It only makes sense if you're going to do a type switch or have multiple code paths that do different things based on the actual type of class
.
答案2
得分: 20
根据您的需求,您至少有两个选项:
- 在结构类型上定义方法
- 接受结构类型作为参数的函数
package main
import "fmt"
type MyClass struct {
Name string
}
func main() {
cls := MyClass{Name: "Jhon"}
// 以下两个调用产生相同的结果
cls.StructMethod() // "Jhon"
FuncPassStruct(cls) // "Jhon"
}
// 在结构类型上定义的方法
func (class MyClass) StructMethod() {
fmt.Println(class.Name)
}
// 接受结构类型作为参数的函数
func FuncPassStruct(class MyClass) {
fmt.Println(class.Name)
}
我相信其他人可能会提供一些我忘记的接口技巧。
英文:
Depending on your needs, you have (at least) two options:
- Method on the struct type
- Func that takes struct type as parameter
<div></div>
package main
import "fmt"
type MyClass struct {
Name string
}
func main() {
cls := MyClass{Name: "Jhon"}
// Both calls below produce same result
cls.StructMethod() // "Jhon"
FuncPassStruct(cls) // "Jhon"
}
// Method on struct type
func (class MyClass) StructMethod() {
fmt.Println(class.Name)
}
// Function that takes struct type as the parameter
func FuncPassStruct(class MyClass) {
fmt.Println(class.Name)
}
I'm sure others may provide some interface wizardry I'm forgetting.
答案3
得分: 3
如果你真的想以通用的方式发送任何结构体,就像你在原始问题中所写的那样(使用空接口参数),以便可以访问AnyStruct.SomeField和AnotherStruct.SomeField,或者AnyOtherStruct.AnyField,我认为Go语言的反射功能是一个不错的选择。
例如,如果你看一下JSON marshal函数,它接受几乎任何结构体作为一个"v"参数传递给一个带有空接口参数的函数。然后,marshal函数最终调用:
e.reflectValue(reflect.ValueOf(v), opts)
但是你可能正在寻找其他答案中提到的一些简单的方法,这些方法不需要高级反射(一种通用的编程方式)。
然而,我发布这个答案是为了其他读者有兴趣在不需要事先知道结构体字段的情况下通用地发送结构体。
JSON解析器需要通用地访问结构体的原因是为了方便用户定义任何他想要的结构体,然后Go语言会自动识别结构体并将其映射到JSON语法。你可以想象有100多种不同的结构体布局,你只想将它们放入一个文本文件中,而不需要事先知道所有结构体的布局-该函数可以在运行时确定,这就是反射的工作原理(其他语言称之为运行时类型信息、元编程等)。
英文:
If you really want to send any struct in generically like it is written in your original question (an empty interface parameter) so that AnyStruct.SomeField and AnotherStruct.SomeField, or AnyOtherStruct.AnyField can be accessed, AFAIK the reflecton features of go are the way to go.
For example if you look at the JSON marshal function it accepts pretty much any struct as a ("v") parameter sent in to a function with an empty interface parameter. Then that marshal function ends up calling
e.reflectValue(reflect.ValueOf(v), opts)
But you are probably looking for something simple as the other answers have suggested, which would not need advanced reflection (a sort of generic way of programming)
However I post this answer in case other readers are interested in sending structs in generally without needing to know up front what the struct fields are.
The reason a JSON parser needs to generically access a struct is for convenience of the user defining any struct he wants, and then Go automagically figures out the struct and maps it to a JSON syntax. You could imagine 100's of different struct layouts that you just want to place into a text file, without knowing all your struct layouts upfront - the function can figure out it at run time, which is how reflection works (other languages call it run time type information, meta programming, and similar).
答案4
得分: 1
请查看Debug和Receive方法。它使用了名为user的结构体,以及它的方法。链接:https://play.golang.org/p/E_WkLWGdeB
package main
import "fmt"
// user定义了程序中的用户。
type user struct {
name string
email string
status string
}
func debug(u user) {
fmt.Printf("%+v\n", u)
}
// notify实现了一个带有值接收器的方法。
func (u user) notify() {
fmt.Printf("User: 发送邮件给 %s<%s>\n", u.name, u.email)
}
// changeEmail实现了一个带有指针接收器的方法。
func (u *user) changeEmail(email string) {
u.email = email
}
func (u *user) changeName(name string) {
u.name = name
}
func (u *user) Send() {
u.notify()
}
// main是应用程序的入口点。
func main() {
// 类型为user的指针也可以用于使用值接收器声明的方法。
john := &user{"John", "john@exemple.com", "enabled"}
john.changeName("John Smith")
john.changeEmail("john@gmail.com")
john.notify()
Receive(john)
debug(user{"Willy", "Willy@exemple.com", "enabled"})
}
func Receive(user interface {
changeName(s string)
changeEmail(s string)
Send()
}) {
user.changeName("Bill")
user.changeEmail("bill@billy-exemple.com")
user.Send()
}
英文:
Please take a look over the Debug ,Receive methods. It uses stuct user, with its methods. https://play.golang.org/p/E_WkLWGdeB
package main
import "fmt"
// user defines a user in the program.
type user struct {
name string
email string
status string
}
func debug(u user) {
fmt.Printf("%+v\n", u)
}
// notify implements a method with a value receiver.
func (u user) notify() {
fmt.Printf("User: Sending User Email To %s<%s>\n", u.name, u.email)
}
// changeEmail implements a method with a pointer receiver.
func (u *user) changeEmail(email string) {
u.email = email
}
func (u *user) changeName(name string) {
u.name = name
}
func (u *user) Send() {
u.notify()
}
// main is the entry point for the application.
func main() {
// Pointers of type user can also be used to methods
// declared with a value receiver.
john := &user{"John", "john@exemple.com", "enabled"}
john.changeName("John Smith")
john.changeEmail("john@gmail.com")
john.notify()
Receive(john)
debug(user{"Willy", "Willy@exemple.com", "enabled"})
}
func Receive(user interface {
changeName(s string)
changeEmail(s string)
Send()
}) {
user.changeName("Bill")
user.changeEmail("bill@billy-exemple.com")
user.Send()
}
答案5
得分: 0
你需要使用.()
语法将参数从接口转换为特定的结构体类型。
package main
import (
"fmt"
)
type MyClass struct {
Name string
}
func test(class interface{}) {
classStr := class.(MyClass)
fmt.Println(classStr.Name)
}
func main() {
test(MyClass{Name: "Jhon"})
}
英文:
You need to cast the parameter from an interface to the specific struct by using the .()
syntax
package main
import (
"fmt"
)
type MyClass struct {
Name string
}
func test(class interface{}) {
classStr := class.(MyClass)
fmt.Println(classStr.Name)
}
func main() {
test(MyClass{Name: "Jhon"})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论