之前有记录过golang的一些基础知识,但是比较琐碎,更像是一种流程。因为之前学的是java,将进行golang与java对比学习
格式控制
Go
新增%T 输出格式
需导入fmt包
不需要;
print 不换行 不空格
println 换行 空格
printf 格式化输出 ("%v",a)
var a int =10
fmt.println("a=",a)
fmt.printf("a=%v\n",a)
fmt.printf("a=%v" a的类型是%T",a,a)
JAVA
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello World");
}
变量常量定义
Go
变量
var 变量名称 类型
//初始化
单变量
var username string
username="zz"
多变量
var 变量名称 变量名称 类型
var (
变量名称 类型
变量名称 类型
)
类型推导
username := "zz"
常量
const pi=3.14159
JAVA
public static final double PI = 3.14;
int i;
String name;
String name = "ZZ";
流程控制
Go
if/switch/for的条件部分都没有圆括号,但必须有花括号。
两种 全局变量和局部变量
if{ 必须紧跟
for循环
for k, v :=range str{}
关键字 值
switch
case
一个分支可以有多个值,case中不需要break
没有while
age :=20
if age>18{
fmt.Println("adult")
}
for i := 0; i < 10; i++ {
fmt.Printf("%d \n", i)
}
var str ="hello golang"
for k,v := range str{
fmt.Printf("key=%v val=%c\n",k,n)
}
var str = "hello"
switch str {
case "good":
fmt.Println("Good morning")
case "hello":
fmt.Println("hello everyone")
default:
fmt.Println("hi")
}
JAVA
if else
do while
for
switch case break
集合
Go
有slice map 数组
会自动初始化 slice 数组 的默认值为0,map的默认值为nil
类型声明写在后面
可以用append来扩容
用make来分配储存空间
slice与数组的区别就是,数组必须定义长度
slice 左闭右开
声明
var arr1 []int //不推荐
初始化
var arr2 = []int{1,2,3,4}
var arr3 = []int{1: 2,2: 4,3: 6}//前一个表示位置,后一个表示值
基于切片的切片
a :=[]string{}
b :=a[1:]
数组
var arr1=[3]int={1,2,3}
map
var map类名 = make(mapKeyType]ValueType)
var userinfo =make (map[string]dtring)
userinfo["username"]="zz"
JAVA
数组
必须用new 实现
public class ArrayTest {
public static void main(String[] args) {
int[] a = new int[5];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
System.out.println(a[3]);
// 定义数组的第一种方式
int a[] = new int[2];
a[0] = 1;
a[1] = 2;
System.out.println(a[1]);
//定义数组的第二种方式
int[] a = {1, 2, 3, 4};
System.out.println(a[2]);
int[] b = new int[]{1, 2, 3, 4};
System.out.println(b[2]);
*/
int[] a = new int[100];
for(int i = 0; i < a.length; i++){
a[i] = i + 1;
}
for(int i = 0; i < a.length; i++){
System.out.println(a[i]);
}
}
}
map
public static void main(String[] args) {
Map< Serializable, Serializable > map = new HashMap< Serializable, Serializable >();
map.put(null,null);
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
if (map.containsKey("a")) {
System.out.println("Key=Ture");
if (map.containsValue("1")) {
System.out.println("value=Ture");
}
}
}
指针及内存
Go
new:分配长度为0的空白内存,返回类型T
make:仅用于切片、map、chan消息管道,返回类型T而不是指针
指针
var a*int
a = new(int)
*a=100 //引用数据类型
var a new(int)
函数
Go
**最大的不同就是“倒序”的类型声明
不需要public,protected,private等访问权限控制
不需要函数原型,引用的函数可以后定义**
func 函数名(参数 (变量名,类型))(返回值){} 类型一样可省略前面的
用type定义一个函数类型
type 函数类型名(int,int)int
匿名函数
func (参数)(返回值){
函数体
}
具体示例可参考https://blog.csdn.net/qq_46595591/article/details/107186427
JAVA
函数格式:修饰符 返回值类型 函数名 ( [ 参数类型1 参数名1,参数类型2 参数名2.... ] ){
// [ ] 里面表示可选项,即参数不是必须的
执行语句...
return 返回值; //返回值的类型必须与返回值类型一致
}
示例
public class method {
public static void main(String[] args) {
method01();
method02(9, 3);
System.out.println("5+6=" + add(5, 6));
}
static void method01() {
System.out.println("这是method01方法,可以通过method01();调用.");
return;
}
static void method02(int num1, int num2) {
method01();
System.out.println("这是method02方法,第一个参数是" + num1 + "第二个参数是" + num2);
}
static int add(int num1, int num2) {
int sum = 0;
sum = num1 + num2;
return sum;
}
}
结构体
Go
支持带名称的初始化
没有public,protected,private等访问权限控制
方法名大写就是public的,小写就是private
结构体可以继承,但一般直接通过接口实现,不同于java
定义
type 类型名 struct{
字段名 字段类型
字段名 字段类型
...
}
结构初始化有七种方法
可以详细参考https://blog.csdn.net/qq_46595591/article/details/107186427
结构体方法
func(接受者变量 接受者类型)方法名(参数列表)(返回参数){
函数体
}
//接受者变量 命名时第一个字母小写
JAVA
继承和实现
public class Test
{
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
接口
Go
非常简单
不需要implements关键字,已经完全编译
type 接口名 interface{
方法名1(参数列表1)返回值列表1
方法名2(参数列表2)返回值列表2
}
可以有空接口,可以接受任何类型的接口
空接口也可以直接像类型一样使用
JAVA
[访问控制符]interface <接口名> {
类型标识符final 符号常量名n = 常数;
返回值类型 方法名([参数列表]);
…
}
interface Flyanimal{
void fly();
}
class Insect {
int legnum=6;
}
class Bird {
int legnum=2;
void egg(){};
}
class Ant extendsInsect implements Flyanimal {
public void fly(){
System.out.println("Ant can fly");
}
}
classPigeon extends Bird implements Flyanimal {
public void fly(){
System.out.println("pigeon can fly");
}
public void egg(){
System.out.println("pigeon can lay eggs ");
}
}
public classInterfaceDemo{
public static void main(String args[]){
Ant a=new Ant();
a.fly();
System.out.println("Ant's legs are"+ a.legnum);
Pigeon p= new Pigeon();
p.fly();
p.egg();
}
}
异常处理
这是java与go之间最大区别之一
Go
golang中没有明确的异常处理语句,一般通过defer和panic解决
闭包
1.闭包是指有权访问另一个函数作用域中的变量的函数
2.创建闭包的常见的方式是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量
写法: 函数里嵌套函数,最后返回里面的函数
defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序执行
panic在任何地方都可生效,但recover只能在defer中有效
JAVA
Java异常机制用到的几个关键字:try、catch、finally、throw、throws
try -- 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出
catch -- 用于捕获异常。catch用来捕获try语句块中发生的异常
finally -- finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止
throw -- 用于抛出异常
throws -- 用在方法签名中,用于声明该方法可能抛出的异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,
就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行
java异常处理方法有很多,不再赘述
try{
可能会发生的异常
}catch(异常类型 异常名(变量)){
针对异常进行处理的代码
}catch(异常类型 异常名(变量)){
针对异常进行处理的代码
}...
[finally{
释放资源代码;
}]
并发和并行
Go
golang并行中最主要的特点就是协程,goroutine
协程是轻量级的线程
在过程式编程中,当调用一个过程的时候,需要等待其执行完才返回
而调用一个协程的时候,不需要等待其执行完,会立即返回
协程十分轻量,Go语言可以在一个进程中执行有数以十万计的协程,依旧保持高性能
通道是协程之间的数据传输通道。通道可以在众多的协程之间传递数据,具体可以值也可以是个引用。通道有两种使用方式
协程可以试图向通道放入数据,如果通道满了,会挂起协程,直到通道可以为他放入数据为止
协程可以试图向通道索取数据,如果通道没有数据,会挂起协程,直到通道返回数据为止
func A(para1, para2, para3, ...) {
...
}
func main() {
go A(para1, para2, para3, ...) //只需加一个go前缀,A()就会并发运行
}
package main
func main() {
ch := make(chan int, 3)
ch <- 1
ch <- 1
ch <- 1
ch <- 1
}
package main
func main() {
ch := make(chan int, 3)
<-ch
}
JAVA
没有协程一说
并发
public synchronized void out2(String name) {
int length = name.length();
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
并行
public void synchronized functionA(){
}
public void functionB(){
synchronized(this){
}
}