Go与Java(6) Go和Java微观对比-5

110 阅读5分钟

15.Go与Java的数组对比

1)go的一维数组

var 数组名 [数组长度]数组类型 = [数组长度]数组类型{元素1,元素2...}

示例1:

package main


import "fmt"
//全局
var my_arr [6]int
var my_arr_1 [3]int = [3]int{1,2,3}
func main() {
   //方法内:
   this_arr := [2]int{1, 2}
   fmt.Println(my_arr)
   fmt.Println(my_arr_1)
   fmt.Println(this_arr)
}

2)二维数组

package main


import "fmt"
//全局
var my_arr [4][6]int
var my_arr_1 [2][3]int = [...][3]int{{1, 2, 3}, {4, 5, 6}}
func main() {
   //方法内:
   this_arr := [2][3]int{{1, 2, 3}, {8, 8, 8}}
   // 第 2 纬度不能用 "..."。
   this_arr2 := [...][2]int{{1, 1}, {2, 2}, {3, 3}}
   fmt.Println(my_arr)
   fmt.Println(my_arr_1)
   fmt.Println(this_arr)
   fmt.Println(this_arr2)
}

 

16.Go有指针概念,Java没有指针概念

Go中有指针的概念,Java中没有指针的概念。

指针简单的说就是存储一个【变量地址】的【变量】。

Go中使用指针的方法

//*+变量类型 = 对应变量类型的指针类型,&+变量名 = 获取变量引用地址

var 指针变量名 *指针变量类型 = &变量名

例如:

var my_point *int = &num

//通过&+指针变量 = 修改原来的变量真实值

&指针变量名 = 修改的变量值

例如:

&my_point = 100;

示例:

 

package main


import "fmt"


func main() {
	// 声明实际变量
	var name string="li_ming"
	// 声明指针变量
	var name_point *string
	// 指针变量的存储地址
	name_point = &name


	//直接访问变量地址
	fmt.Println("name 变量的地址是:", &name  )


	// 指针变量的存储地址
	fmt.Println("name_point变量储存的指针地址:", name_point )


	// 使用指针访问值
	fmt.Println("*name_point 变量的值:", *name_point )
}

 

输出结果:

 

name 变量的地址是: 0x10ae40f0

name_point变量储存的指针地址: 0x10ae40f0

*name_point 变量的值: li_ming

17.Go语言的中new,make和Java中的new对象有什么区别?

 

首先,Java中的new关键字代表创建关于某一个类的一个新的对象。

如:  

 List list = new ArrayList(); 

Go中的创建一个struct结构体的对象,是不需要用new关键字的,参考【20】中有代码示例讲解如何创建结构体对象。  

Go中new的概念是和内存相关的,我们可以通过new来为基础数据类型申请一块内存地址空间,然后把这个把这个内存地址空间赋值给

一个指针变量上。(new主要就是为基础数据类型申请内存空间的,当我们需要一个基础数据类型的指针变量,并且在初始化这个基础指针变量时,不能确定他的初始值,此时我们才需要用new去内存中申请一块空间,并把这空间绑定到对应的指针上,之后可以用该指针为这块内存空间写值。new关键字在实际开发中很少使用,和java很多处用new的情况大不相同)

参考如下示例代码:

 

package main


import "fmt"


func main() {
   var num *int
   //此处num是nil
   fmt.Println(num)
   //此处会报空指针异常,因为num为nil,没有申请内存空间,所以不能为nil赋值
   *num = 1
   fmt.Println(*num)
}

 

改为如下代码即可:

 

package main


import "fmt"


func main() {
   //在内存中申请一块地址,并把内存地址存入num
   var num = new(int)
   //此处num的值是申请出来的内存空间地址值,一个十六进制的数字
   fmt.Println(num)
   //正常
   *num = 1
   fmt.Println(*num)
}

 

接下来我们来看一个go中的make是做什么用的?

go中的make是用来创建slice(切片),map(映射表),chan(线程通信管道)这三个类型的对象的,返回的就是对应类型的对象,他的作用就相当于Java中new一个ArrayList,new一个HashMap时候的new的作用,只不过是go语法规定用make来创建slice(切片),map(映射表),chan(线程通信管道)。

  示例代码如下:

package main


import "fmt"


func main() {


   //make只能为map,channel,slice申请分配内存,只有这三种,没有第四种
   //所有通过make创建的这三种类型都是引用类型,传递参数时虽然是引用值传递,
   //但是对方法内引用变量参数的修改可以影响到外部的引用变量
   //1.通过make创建map对象  如下代码类似于Java中 Map<String,Integer> myMap = new HashMap<>();
   //在这里make就是申请分配map的内存,和java中创建map的new一样
   myMap := make(map[string]int)
   myMap["li_ming"] = 20


   //2.通过make创建channel,make函数内可以有一个参数,也可以有两个参数,有两个参数时第二个参数
   //为通道的缓存队列的长度
   //2.1) 只有一个参数,通道的缓存队列长度此时为0,也就是无缓存。
   //创建一个传输int类型数据的通道
   myChan := make(chan int)
   fmt.Println(myChan)
   //2.2) 有两个参数,第二个参数2代表此时代表缓存队列的长度为2
   //创建一个传输int类型数据的通道,缓存为2
   mychan2 := make(chan int,2)
   fmt.Println(mychan2)
   //此处暂时不做通道缓存队列数多少有何区别的讲解


   //3.通过make创建slice切片
   //有两种方式,一种是两个参数,一种是三个参数
   //我们只有在创建一个空的切片时才会使用make
   //如果通过一个已有的数组创建切片往往是下面的形式
   //创建一个底层数组
   myArr := []int{1,2,3,4,5}
   //如果通过一个数组创建切片,往往是用 原始数组变量名[切片起始位置:切片结束位置] 创建一个切片
   mySlice1 := myArr[2:4]
   fmt.Println(mySlice1)
   //我们如果是想创建一个空的slice,则用make创建切片
   //如下形式 make(int[],num1,num2)
   //num1 = 切片的长度(默认分配内存空间的元素个数)
   //num2 = 切片的容量(解释:底层数组的长度/切片的容量,超过底层数组长度append新元素时会创建一个新的底层数组,
   //不超过则会使用原来的底层数组)


   //代表底层数组的长度是4,默认给底层数组的前两个元素分配内存空间
   //切片指向前两个元素的地址,如果append新元素,在元素数小于4时都会
   //在原来的底层数组的最后一个元素新分配空间和赋值,
   //append超过4个元素时,因为原数组大小不可变,也也存储不下了,
   //所以会新创建一个新的底层数组,切片指向新的底层数组
   mySliceEmpty := make([]int,2,4)
   fmt.Println(mySliceEmpty)


   //两个参数,代表切片的长度和切片的容量(底层数组长度)均为第二个参数那个值
   mySliceEmpty2 := make([]int,5)
   fmt.Println(mySliceEmpty2)
}

 

18.Go相关的数据容器和Java的集合框架对比

Go中有的数据结构:数组,切片,map,双向链表,环形链表,堆

Go自己的类库中没有set,没有集合(List),但是第三方库有实现。

Java中有: Map,Set,List,Queue,Stack,数组

Java中没有切片的概念。

Go中的数组打印格式是[1,2,3,4,5]

Go中的切片打印格式是[[1,2,3]]

Go中切片的概念:切片是数组的一个子集,就是数组截取某一段。

Go的map和Java的map大致相同

19.Go中的函数,Go的方法和Java中的方法对比

 

1).Go中的函数定义

  Go中返回值可以有多个,不像Java中多个值得封装到实体或map返回

//注:【】内的返回值可不写,无返回值直接把返回值部分全部去掉即可。

func 函数名(变量1 变量类型,变量2 变量2类型...)【(返回值1 类型1,返回值2 类型2...)】 { //注意:这个方法的右中括号必须和func写在同一行才行,否则报错,不能按c语言中的换行写

示例1:

package main


import "fmt"


func main() {
   //定义局部变量
   var a int = 100
   var b int = 200
   var result int


   //调用函数并返回最大值
   result = max(a, b)


   fmt.Println( "最大值是 :", result )
}


/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 定义局部变量 */
   var result int


   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result
}

 

示例2:返回多个值

 

package main


import "fmt"


func main() {
   a, b := swap("li_ming", "xiao_hong")
   fmt.Println(a, b)
}


func swap(x, y string) (string, string) {
   //返回多个值
   return y, x
}

 

注意点:函数的参数:基础类型是按值传递,复杂类型是按引用传递

 

示例3: 函数的参数:变长参数传递

 

package main


import "fmt"


func main() {
	manyArgs(1,2,"2","3","4")
	manyArgs(1,2,"5","5","5")
	dataStr := []string{"11","11","11"}
	//传数组也可以,加三个点
	manyArgs(1,2,dataStr...)
}


//可变参数必须放在最后面
func manyArgs(a int,b int ,str ...string ){
	for i,s := range str {
		fmt.Println(i,s)
	}
}

 

注意点:函数的返回值:如果有返回值,返回值的类型必须写,返回值得变量名根据情况可写可不写。

 

示例4: defer:推迟执行(类似于java中的finally)

 

package main


import "fmt"


func main() {
   testMyFunc();
}




func testDefer1() {
   fmt.Println("print defer1")
}
func testDefer2() {
   fmt.Println("print defer2")
}


func testMyFunc() {
   //defer会在方法返回前执行,有点像java中的finally
   //defer写在任意位置均可,多个defer的话按照逆序依次执行
   defer testDefer2()
   defer testDefer1()
   fmt.Println("print my func")
}

 

示例5 :丢弃返回值

 

package main


import "fmt"


func main() {
   //方式一丢弃:丢弃num1和str
   _,num2,_:= testFun(1,2,"3");
   fmt.Println(num2)
   //方式二丢弃:
   _,num3,_:= testFun(1,3,"4");
   fmt.Println(num3)
}


func testFun(num1,num2 int,str string) (n1 int,n2 int,s1 string){
   n1 = num1
   n2 = num2
   s1 = str
   return
}
func testFun2(num1,num2 int,str string) (int,int,string){
   return num1,num2,str
}

 

2).Java中的方法定义

访问修饰符 返回值类型 方法名(参数1类型 参数1,参数2类型 参数2...) {

return 返回值;

}

 

示例:

 

 public Integer doSomething(String name,Integer age) {
    
 		return 20;
 }