函数的语法

huangapple go评论93阅读模式
英文:

Syntax of a function

问题

我正在查看Golang文档中的“编写Web应用程序”章节,并找到了以下函数的语法:

func (p *Page) save() error {
    filename := p.Title + ".txt"
    return os.WriteFile(filename, p.Body, 0600)
}

从文档中可以看到,这是一个名为save的方法,它以指向Page的指针p作为接收器。它不接受任何参数,并返回一个error类型的值。

  1. 声明函数时,使用func save(p *Page) error{}的方式有什么区别?接收器和函数参数之间有什么区别?
    • 使用接收器的方式可以将函数与特定类型关联起来,使其成为该类型的方法。这样,我们可以通过该类型的实例来调用该方法。而使用函数参数的方式则将函数作为独立的实体,需要通过传递参数来调用。
  2. 为什么返回一个error类型的值,而我看到它返回的是os包中的一个函数?
    • 在这个例子中,os.WriteFile函数返回一个error类型的值,表示文件写入操作可能会出现错误。通过返回该值,我们可以在调用该方法的地方进行错误处理。

希望对你有帮助!如果还有其他问题,请随时提问。

英文:

I am looking into the chapter Writing Web Application of the Golang docs, and found this syntax of a function:

func (p *Page) save() error {
    filename := p.Title + ".txt"
    return os.WriteFile(filename, p.Body, 0600)
}

And from the docs... This is a method named save that takes as its receiver p, a pointer to Page . It takes no parameters, and returns a value of type error.

  1. What is the difference between declaring the function like this func save(p *Page) error{}? What is the difference between a receiver and a function parameter?
  2. Why is it returning a value of type error, when I see it is returning a function from the os package?

Thank you in advance, may be a dumb question but I'm kinda new to Golang,

答案1

得分: 1

  1. func save(p *Page) error{}func (p *Page) save() error之间的区别是什么?接收器和函数参数之间的区别是什么?

这两种方式在功能上是相同的,这是Go在编译时的底层操作。但是它们有一些语义上的区别:

  • 最大的区别是,你可以像这样调用func (p *Page) save() errorsomePage.save(),而调用func save(p *Page) error则是save(somePage)
  • 通过go.dev生成的文档将把它列为包中的一个函数,而不是Page的方法(假设它是一个导出的函数)。
  • 声明一个func save(p *Page) error不会使Page实现一个接口,比如interface{ save() },而方法会实现该接口。
  • 当调用方法时,Go会自动在指针和值之间进行转换,但是对于函数,你必须始终自己传递正确的参数类型。例如:
type Page struct {
	Field string
}

func (p *Page) PtrString() string {
	return p.Field
}

func (p Page) String() string {
	return p.Field
}

func PageString(page Page) string {
	return page.Field
}

func PagePtrString(page *Page) string {
	return page.Field
}

func main() {
	p := Page{Field: "Hello world"}

	// 两种方式都可以工作
	fmt.Println(p.String())
	fmt.Println(p.PtrString()) // 这里隐式地传递了一个指针

	// 这种方式可以工作
	fmt.Println(PageString(p))

	// 这个无法编译通过
	fmt.Println(PagePtrString(p)) // cannot use p (type Page) as type *Page in argument to PagePtrString

	// 但是这个可以,你必须指定你要传递一个指针
	fmt.Println(PagePtrString(&p))
}

这里有一个链接,详细介绍了指针接收器和值接收器之间的区别。

  1. 当我看到它返回一个error类型的值时,为什么它返回的是os包中的一个函数?

它并不返回函数本身,它调用了os.WriteFile的返回值,而该返回值是error类型的。

英文:

> 1. What is the difference between declaring the function like this func save(p *Page) error{}? What is the difference between a receiver and a function parameter?

These are functionally identical, this is what Go does underwater when compiling. But there are a few semantic differences:

  • The largest difference is that you would call func (p *Page) save() error like somePage.save() and func save(p *Page) error as save(somePage).
  • Documentation generated by go.dev will list it as a function in the package, not as method for Page (assuming it was an exported function).
  • When declaring a func like func save(p *Page) error will not make Page implement an interface like interface{ save() } where as the method will.
  • Go will convert between pointers and values for you when calling a method, but for functions you must always pass the correct param type yourself. For example:
type Page struct {
	Field string
}

func (p *Page) PtrString() string {
	return p.Field
}

func (p Page) String() string {
	return p.Field
}

func PageString(page Page) string {
	return page.Field
}

func PagePtrString(page *Page) string {
	return page.Field
}

func main() {
	p := Page{Field: "Hello world"}

	// Both work
	fmt.Println(p.String())
	fmt.Println(p.PtrString()) // This passes a pointer implicitly

	// This works
	fmt.Println(PageString(p))

	// This doesn't compile
	fmt.Println(PagePtrString(p)) // cannot use p (type Page) as type *Page in argument to PagePtrString

	// But this does, you have to specify you want to pass a pointer
	fmt.Println(PagePtrString(&p))
}

Here is a link with more details about the difference between pointer and value receivers.

> 2. Why is it returning a value of type error, when I see it is returning a function from the os package?

It doesn't return the function itself, it calls it and returns the return value of os.WriteFile, which is error

huangapple
  • 本文由 发表于 2022年1月20日 06:26:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/70778535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定