编码规范
代码排版
1. 花括号换行风格
在Java中,每一条语句以分号";"分隔,是否换行不影响代码的正确性。
在python中,取消了分号分隔方式,同时也取消了括号对于代码逻辑的作用(python中各种括号用于不同的数据类型)。因此采用了一种严格的缩进规则来控制代码规范。
而Golang取消了Java中的分号分隔,采用换行划分语句,但是保留了括号的使用。
但是Golang对花括号的使用较为严格。
在Java中,以下两种书写方式都是正确的
public String getString(Integer num) {
return num.toString();
}
public String getString(Integer num)
{
return num.toString();
}
在Golang中只允许一种格式:
func getString(num int) string {
return strconv.Itoa(num)
}
2. 无用变量声明
在Java中,变量可以声明之后,可以不被使用。
而Golang中声明的变量必须被使用,否则需要使用_来替代掉变量名,表明该变量不会被使用到:
func getString(num int) string {
var temp = num // 没有使用者,无法编译
var _ = num // 正常编译
return strconv.Itoa(num)
}
3. 可见域规则
Java对方法、变量及类的可见域规则是通过private、protected、public关键字来控制的。
而Golang中控制可见域的方式只有一个,当字段首字母开头是大写时说明其是对外可见的、小写时只对包内成员可见。
Golang
- entity
package entity
type Person struct {
Name string
Age int
id string
}
type student struct {
detail Person
}
func test() {
// 本包内可见
person := &student{detail: Person{
Name: "Jrobin",
Age: 24,
id: "001",
}}
fmt.Println(person)
}
- main
package main
import (
"fmt"
entity "entity"
)
func main() {
// id字段不可见
person := &entity.Person{
Name: "Jrobin",
Age: 24,
}
fmt.Println(person)
}
Java
- Person
public class Person {
public String name;
public int age;
private String id;
private class Student{
Person detail;
}
public void test(){
//本包内可见
Student student=new Student();
student.detail.name="Jrobin";
student.detail.age=24;
student.detail.id="001";
System.out.println(toString());
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", id='" + id + '\'' +
'}';
}
}
- main
public class Main {
public static void main(String[] args) {
//student类不可见
Person person=new Person();
person.name="Jrobin";
person.age=24;
//id字段不可见
}
}
此处Java代码设计仅为了尽可能与Golang代码进行对比,实际Golang的结构体与Java的类并不完全对应。
变量声明和初始化
变量声明语法
- Java
// Object:要声明的类型、v:变量名称、new Object()变量初始化
Object v = new Object();
int v1;
String v2;
int[] v3=new int[10];
int[] v4=new int[]{0,1,2};
Map<String,Integer> v5=new HashMap<>();//map,key为string类型,value为int类型
private int v6(int a){return 0;}
int v7,v8;
- Golang
// var:变量定义、v1:变量名称、int:变量类型
var v1 int
var v2 string
var v3 [10]int // 数组
var v4 []int // 数组切片
var v5 struct {
f int
}
var v6 *int // 指针
var v7 map[string]int // map,key为string类型,value为int类型
var v8 func(a int) int
var v9,v10 int //v9和v10都声明为int型
也可以采用:=自动推测变量类型:
var v1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型
值类型和引用类型
Golang的类型系统与Java相差不大,但是需要注意的是Java中的数组是属于引用类型,而Golang中的数组属于值类型,当向方法中传递数组时,Java可以直接通过该传入的数组修改原数组内部值(浅拷贝),但Golang则会完全复制出一份副本来进行修改(深拷贝):
- Java
public static void main(String[] args) {
int[] array = {1, 2, 3};
change(array);
System.out.println(Arrays.toString(array)); // -1,2,3
}
private static void change(int[] array) {
array[0] = -1;
}
- Golang
func main() {
array := [...]int{1, 2, 3}
change(array)
fmt.Println(array) // 1,2,3
}
func change(array [3]int) {
array[0] = -1
}
在Golang中,只有切片、指针、channel、map及func属于引用类型,也就是在传递参数的时候,实质上复制的都是他们的指针,内部的修改会直接影响到外部:
func main() {
slice := []int{1, 2, 3}
changeSlice(slice)
fmt.Println(slice) // -1,2,3
mapper := map[string]int {
"num": 0,
}
changeMap(mapper)
fmt.Println(mapper) // num = -1
array := [...]int{1, 2, 3}
changePointer(&array)
fmt.Println(array) // -1,2,3
intChan := make(chan int, 1)
intChan <- 1
changeChannel(intChan)
fmt.Println(<- intChan) // -1
}
func changeChannel(intChan chan int) {
<- intChan
intChan <- -1
}
func changePointer(array *[3]int) {
array[0] = -1
}
func changeMap(mapper map[string]int) {
mapper["num"] = -1
}
func changeSlice(array []int) {
array[0] = -1
}