在Golang中区别与Java最显著的一点是,Golang不存在“类”这个概念,组织数据实体的结构在Golang中被称为结构体。函数可以脱离“类”而存在,函数可以依赖于结构体来调用或者依赖于包名调用。
Golang中的结构体放弃了继承、实现等多态概念,结构体之间可使用组合来达到复用方法或者字段的效果。
要声明一个结构体只需使用type + struct关键字即可:
type Person struct {
Name string
Age int
id string
}
使用结构体:
personPoint := new(entity.Person) // 通过new方法创建结构体指针
person1 := entity.Person{} // 通过Person{}创建默认字段的结构体
person2 := entity.Person{ // 通过Person{Name:x,Age:x}创建结构体并初始化特定字段
Name: "Jrobin",
Age: 24,
}
fmt.Println(personPoint) // &{ 0 }
fmt.Println(person1) // { 0 }
fmt.Println(person2) // {Jrobin 24 }
函数:源于面向过程编程
方法:源于面向对象编程
在Java中,所有的函数都包含在类中,因此在Java中,函数和方法属于同一个概念。
而在Golang中,函数不基于结构体而是基于包名调用,方法基于结构体调用。
package entity
import "fmt"
type Person struct {
Name string
Age int
id string
}
// Person结构体/指针可调用的"方法",属于Person结构体
func (p *Person) Solve() {
fmt.Println(p)
}
// 任何地方都可调用的"函数",不属于任何结构体,可通过entity.Solve调用
func Solve(p *Person) {
fmt.Println(p)
}
func main() {
personPoint := new(entity.Person) // 通过new方法创建结构体指针
entity.Solve(personPoint) // 函数调用
personPoint.Solve() // 方法调用
}
C/C++存在显示指针操作,而且指针的使用非常灵活复杂,也是C/C++的独特之处。
在Java中不存在显式的指针操作。
而Golang中存在显式的指针操作,但是Golang的指针不像C那么复杂,不能进行指针运算。
Golang使用 * 来定义和声明指针,通过&来取得对象的指针。
func main() {
p1 := entity.Person{
Name: "Jrobin",
Age: 24,
}
changePerson(p1)
fmt.Println(p1.Name) // Jrobin
changePersonByPointer(&p1)
fmt.Println(p1.Name) // zhuzhen
}
func changePersonByPointer(person *entity.Person) {
person.Name = "zhuzhen"
}
func changePerson(person entity.Person) {
person.Name = "zhuzhen"
}
public class Main {
public static void main(String[] args) {
Person person=new Person();
person.name="Jrobin";
person.age=24;
changePerson(person);
System.out.println(person.name); //zhuzhen
int num=10;
changeNum(num);
System.out.println(num); //10
}
private static void changePerson(Person person){
person.name="zhuzhen";
}
private static void changeNum(int num){
num=20;
}
}
Java和Golang方法传参时传递的都是值类型,在Java中如果传递了基本类型,则会传递一个副本,方法中的操作不会改变原始的变量值;如果传递了引用类型(对象、数组等)会复制其指针进行传递, 而在Golang中必须要显式传递Person的指针,不然只是传递了该对象的一个副本。
注意,如果结构体中需要组合其他结构体,那么建议采用指针的方式去声明,否则会出现更新丢失问题。
以下是Golang方法的一个隐式指针转换,结构体调用方法时,如果传递的是对象,那么会被自动转化为指针调用:
type Person struct {
Name string
Age int
}
// Person结构体/指针可调用的"方法",属于Person结构体
func (p *Person) Solve() {
fmt.Println(p)
}
func main() {
p := entity.Person{
Name: "Jrobin",
Age: 24,
}
pp := &p
pp.Solve() // 显式
p.Solve // 隐式,自动将p转化为&p
}
在Golang中,对结构体进行"&"取地址操作,视为对该类型进行一次new的实例化操作。