• go中的结构体和方法
  • 发布于 1周前
  • 58 热度
    0 评论
一.结构体
结构体创建
在go中没有其他编程语言中的class,go中只有struct。我们通过创建一个treeNode的例子来看看如何创建和对结构体进行赋值
package main
type treeNode struct {
  value       int
  left, right *treeNode
}
func main(){
  var root treeNode
  fmt.Println(root)
  root = treeNode{value: 3}
  root.left = &treeNode{}
  root.right = &treeNode{5, nil, nil}
}

当然,我们也可以通过关键字new来初始化结构体

package main
type treeNode struct {
  value       int
  left, right *treeNode
}
func main(){
  root = treeNode{value: 3}
  root.left.right = new(treeNode)
}

为结构体创建方法
在实际业务中,我们可能需要打印中上面结构体的value,我们可以写这样的一个函数。也就是把treeNode结构体作为参数,然后打印出这个结构体的value即可。
package main
import "fmt"
type treeNode struct {
  value       int
  left, right *treeNode
}
// 堆代码 duidaima.com
func printVal(t treeNode){
  fmt.Println(t.value)
}
func main(){
  root = treeNode{value: 3}
  root.left.right = new(treeNode)
  printVal(root) // 3
}
要实现上面的功能,go还提供了类似class的一种语法,就是这样
package main
import "fmt"
type treeNode struct {
  value       int
  left, right *treeNode
}

func (t treeNode) printVal(){
  fmt.Println(t.value)
}
func main(){
  root = treeNode{value: 3}
  root.left.right = new(treeNode)
  root.printVal() // 3
}
上面两种方式都实现了同样的功能,从语法层面,无非就是将参数treeNode放在函数名前面还是后面而已。第二种方式,我们称之为结构体方法。

值接收者和指针接收者
根据我们在之前的文章,我们知道,go在参数传递的时候,都是值类型传递 ,当然,结构体方法也不例外,也使用的是值传递,我们可以看一下下面的例子。为了验证结论,我们先创建一个setValue方法
package main

import "fmt"

type treeNode struct {
  value       int
  left, right *treeNode
}

func (tree treeNode) setValue(val int) {
  tree.value = val
}

func (tree treeNode) printValue() {
  fmt.Println(tree.value)
}

func main() {
  root := treeNode{value: 3}

  root.setValue(4)
  root.printValue() // 3 【setValue中会讲结构体复制出来一份,然后重新复制,所以原来原来结构体value并未发生变化】
}
如果想让结构体内容发生变化,我们在传递的时候,使用指针即可,就像这样
package main

import "fmt"

type treeNode struct {
  value       int
  left, right *treeNode
}

func (tree *treeNode) setValue(val int) {
  tree.value = val
}

func (tree *treeNode) printValue() {
  fmt.Println(tree.value)
}

func main() {
  root := treeNode{value: 3}

  root.setValue(4)
  root.printValue() // 4 【因为传递的是指针,所以修改之后,原结构体也发生变化了】
}
我们称第一种方式为值接收者,第二种方式称为指针接收者。

值接收者 VS 指针接收者
要改变内容必须使用指针接收者
出于性能方面的考虑,结构体过大,也要考虑指针接收者
为了保证一致性,如果有指针接收者,最好都是使用指针接收者
值接收者是go特有的,指针接收者其他都有,比如java中有this关键字,python中有self

值/指针接收者均可以接受值/指针


二.构造函数
go语言没有构造函数的概念,但是有些时候,我们可以通过工厂函数来完成构造函数
func createNode(value int) *treeNode {
  return &treeNode{value: value}
}
应用的时候,我们可以这样
package main
import "fmt"

type treeNode struct {
  value       int
  left, right *treeNode
}

func main(){
  root := createNode(3)
  fmt.Println(root.value) // 3
}
注:在这个位置返回了局部变量的地址
在C++中,是一个典型的错误,但是在go中却可以。
用户评论