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

124 阅读6分钟

20.Go的内置函数和Java的默认导入包java.lang.*

为了在Java中快速开发,Java语言的创造者把一些常用的类和接口都放到到java.lang包下,lang包下的特点就是不用写import语句导入包就可以用里面的程序代码。

Go中也有类似的功能,叫做Go的内置函数,Go的内置函数是指不用导入任何包,直接就可以通过函数名进行调用的函数。

Go中的内置函数有:  

close 关闭channel

len 求长度

make 创建slice,map,chan对象  

append 追加元素到切片(slice)中

panic 抛出异常,终止程序

recover 尝试恢复异常,必须写在defer相关的代码块中

参考示例代码1:

 

package main


import "fmt"


func main() {


   array := [5]int{1,2,3,4,5}
   str := "myName"
   //获取字符串长度
   fmt.Println(len(str))
   //获取数组长度
   fmt.Println(len(array))
   //获取切片长度
   fmt.Println(len(array[1:]))


   //make创建channel示例
   intChan := make(chan int,1)
   //make创建map示例
   myMap := make(map[string]interface{})
   //make创建切片
   mySlice := make([]int,5,10)


   fmt.Println(intChan)
   fmt.Println(myMap)
   fmt.Println(mySlice)


   //关闭管道
   close(intChan)
   //为切片添加元素
   array2 := append(array[:],6)
   //输出
   fmt.Println(array2)


   //new案例
   num := new(int)
   fmt.Println(num)


}

 

参考示例代码2:panic和recover的使用

 

他们用于抛出异常和尝试捕获恢复异常

 

func func1() {
	fmt.Println("1")
}


func func2() {
	// 刚刚打开某资源
	defer func() {
		err := recover()
		fmt.Println(err)
		fmt.Println("释放资源..")
	}()
	panic("抛出异常")
	fmt.Println(2")
}


func func3() {
	fmt.Println("3")
}


func main() {
	func1()
	func2()
	func3()
}

 

Java中的java.lang包下具体有什么在这里就不赘述了,请参考JavaAPI文档:

 

JavaAPI文档导航:www.oracle.com/cn/java/tec…

 

21.Go的标准格式化输出库fmt和java的输出打印库对比

 

Java的标准输出流工具类是java.lang包下的System类,具体是其静态成员变量PrintStream类。

他有静态三个成员变量:

分别是PrintStream类型的out,in,err

我们常见System.out.println(),实际上调用的就是PrintStream类对象的println方法。

 


 

Go中的格式化输出输入库是fmt模块。

  fmt在Go中提供了输入和输出的功能,类型Java中的Scanner和PrintStream(println)。  

它的使用方法如下:

Print:   原样输出到控制台,不做格式控制。
Println: 输出到控制台并换行
Printf : 格式化输出(按特定标识符指定格式替换)
Sprintf:格式化字符串并把字符串返回,不输出,有点类似于Java中的拼接字符串然后返回。
Fprintf:来格式化并输出到 io.Writers 而不是 os.Stdout

 

详细占位符号如下:

 

代码示例如下:

 

22.Go的面向对象相关知识

 

1.封装属性(结构体)

  Go中有一个数据类型是Struct,它在面向对象的概念中相当于Java的类,可以封装属性和封装方法,首先看封装属性如下示例:

package main


import "fmt"


//示例
type People struct {
   name string
   age int
   sex bool
}
func main(){


   //示例1:
   var l1 People
   l1.name = "li_ming"
   l1.age = 22
   l1.sex = false
   //li_ming
   fmt.Println(l1.name)


   //示例2
   var l2 *People = new(People)
   l2.name = "xiao_hong"
   l2.age = 33
   l2.sex = true
   //xiao_hong xiao_hong
   fmt.Println(l2.name,(*l2).name)


   //示例3:
   var l3 *People = &People{ name:"li_Ming",age:25,sex:true}
   //li_Ming  li_Ming
   fmt.Println(l3.name,(*l3).name)
}

2.封装方法(方法接收器)

如果想为某个Struct类型添加一个方法,参考如下说明和代码:

go的方法和Java中的方法对比,go的函数和go方法的不同

Go中的函数是不需要用结构体的对象来调用的,可以直接调用  

Go中的方法是必须用一个具体的结构体对象来调用的,有点像Java的某个类的对象调用其方法

我们可以把指定的函数绑定到对应的结构体上,使该函数成为这个结构体的方法,然后这个结构体的对象就可以通过.来调用这个方法了

绑定的形式是:在func和方法名之间写一个(当前对象变量名 当前结构体类型),这个叫方法的接受器,其中当前对象的变量名就是当前结构体调用该方法的对象的引用,相当于java中的this对象。

参考如下示例为Student学生添加一个learn学习的方法  

package main


import "fmt"


type Student struct  {
   num int //学号
   name string //姓名
   class int  //班级
   sex  bool  //性别
}


//给Student添加一个方法
//这里的(stu Student)中的stu相当于java方法中的this对象
//stu是一个方法的接收器,接收是哪个对象调用了当方法
func (stu Student) learn() {
   fmt.Printf("%s学生正在学习",stu.name)
}


func main() {
   stu := Student{1,"li_ming",10,true}
   stu.learn()
}

 

方法的接收器也可以是指针类型的

 

参考如下案例:

 

package main


import "fmt"


type Student struct  {
   num int //学号
   name string //姓名
   class int  //班级
   sex  bool  //性别
}


//这里方法的接收器也可以是指针类型
func (stu *Student) learn() {
   fmt.Printf("%s学生正在学习",stu.name)
}


func main() {
   //指针类型
   stu := &Student{1,"li_ming",10,true}
   stu.learn()
}

 

注意有一种情况,当一个对象为nil空时,它调用方法时,接收器接受的对于自身的引用也是nil,需要我们做一些健壮性的不为nil才做的判断处理。

 

3.Go的继承(结构体嵌入)

Go中可以用嵌入结构体实现类似于继承的功能:

参考如下代码示例:

package main


import "fmt"


//电脑
type Computer struct {
	screen string //电脑屏幕
	keyboard string //键盘
}


//计算方法
func (cp Computer) compute(num1,num2 int) int{
	return num1+num2;
}


//笔记本电脑
type NoteBookComputer struct{
	Computer
	wireless_network_adapter string //无线网卡
}
func main() {
	var cp1 NoteBookComputer = NoteBookComputer{}
	cp1.screen = "高清屏"
	cp1.keyboard = "防水键盘"
	cp1.wireless_network_adapter = "新一代无线网卡"
	fmt.Println(cp1)
	fmt.Println(cp1.compute(1,2))
}

 

需要注意的是,Go中可以嵌入多个结构体,但是多个结构体不能有相同的方法,如果有参数和方法名完全相同的方法,在编译的时候就会报错。所以Go不存在嵌入多个结构体后,被嵌入的几个结构体有相同的方法,最后不知道选择执行哪个方法的情况,多个结构体方法相同时,直接编译就会报错。

 

参考如下示例:

 

package main


import "fmt"


func main() {
   man := Man{}
   fmt.Println(man)
   //下面的代码编译会报错
   //man.doEat()


}
type Man struct {
   FatherA
   FatherB
}


func (p FatherA)  doEat() {
   fmt.Printf("FatherA eat")
}
func (t FatherB)  doEat() {
   fmt.Printf("FatherB eat")
}




type FatherB struct {


}


type FatherA struct  {


}

 

4.Go的多态(接口)

接下来我们讲Go中如何通过父类接口指向具体实现类对象,实现多态:

  go语言中的接口是非侵入式接口。

java语言中的接口是侵入式接口。

侵入式接口是指需要显示的在类中写明实现哪些接口。  

非侵入式接口是指不要显示的在类中写明要实现哪些接口,只需要方法名同名,参数一致即可。

参考如下代码示例:接口与多态

package main


import "fmt"


//动物接口
type Animal interface{
   eat()     //吃饭接口方法
   sleep()       //睡觉接口方法
}
//小猫
type Cat struct {


}
//小狗
type Dog struct {


}
//小猫吃方法
func (cat Cat) eat() {
   fmt.Println("小猫在吃饭")
}
//小猫睡方法
func (cat Cat) sleep(){
   fmt.Println("小猫在睡觉")
}
//小狗在吃饭
func (dog Dog) eat(){
   fmt.Println("小狗在吃饭")
}
//小狗在睡觉
func (dog Dog) sleep(){
   fmt.Println("小狗在睡觉")
}


func main() {
   var cat Animal = Cat{}
   var dog Animal = Dog{}
   cat.eat()
   cat.sleep()
   dog.eat()
   dog.sleep()
}

 

接口可以内嵌接口

 

参考如下代码示例:

 

package main
//内嵌接口
//学习接口,内嵌听和看学习接口
type Learn interface {
   LearnByHear
   LearnByLook
}
//通过听学习接口
type LearnByHear interface {
   hear()
}
//通过看学习
type LearnByLook interface {
   look()
}