NipGeihou's blog NipGeihou's blog
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档

NipGeihou

我见青山多妩媚,料青山见我应如是
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档
  • Java视角看Go

    • 前言
    • 环境安装
    • 介绍
    • 基本语法
      • 第一个程序
      • 变量声明
      • 常量声明
      • 函数
        • 格式
        • 单返回值
        • 多返回值
      • 导包与init()
      • 安装依赖
      • 匿名导包与别名
      • 指针
        • 没有使用的场景
        • 使用指针
      • defer语句(类似finally)
    • 集合
    • 面向对象
    • 反射
    • 协程
    • 常见库
  • other

  • 笔记

  • 代码片段

  • Golang
  • Java视角看Go
NipGeihou
2022-12-30
目录

基本语法

# 第一个程序

mkdir go-project
cd go-project
#  初始化 Go 模块:模块名一般使用 Git 仓库路径或者自定义名称
go mod init github.com/nipgeihou/go-project

# 执行后会在目录生成一个go.mod文件,类似于pom.xml
    package main // 程序包名,package main告诉编译器这是一个可执行程序,而不是作为另一个程序的一部分使用的库包;除此以外应与文件名一致
    
    import (
        "fmt"
        "time"
    )
    
    // main函数
    func main() {
        fmt.Println("Hello, World!")
        time.Sleep(1 * time.Second)
    }
    
    class Main {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
    
    // Make sure to add code blocks to your code group

    # 变量声明

    package main
    
    import "fmt"
    
    // 全局变量,只适用方法1、2、3
    var aa int
    var bb string = "hello"
    var cc = true
    
    func main() {
    	// 方法1:默认的值是0
    	var a int
    	fmt.Println("a = ", a)
    
    	// 方法2:指定值
    	var b int = 10
    	fmt.Println("b = ", b)
    
    	// 方法3:根据值自动推导类型
    	var c = 30
    	fmt.Println("c = ", c)
    	var d = "hello"
    	fmt.Println("d = ", d)
    
    	// 方法4(常用):省略var,注意 := 左侧的变量不应该是已经声明过的,否则会导致编译错误
    	e := 50
    	fmt.Println("e = ", e)
    	fmt.Printf("e type is %T", e)
    
    	// 打印全局变量
    	fmt.Printf("aa = %d, bb = %s, cc = %t", aa, bb, cc)
    
    	// 声明多个变量
    	var xx, yy int = 100, 200
    	fmt.Println("xx = ", xx, "yy = ", yy)
    
    	var kk, ll = 300, "hello"
    	fmt.Println("kk = ", kk, "ll = ", ll)
    
    	var (
    		mm = 400
    		nn = "hello"
    	)
    	fmt.Println("mm = ", mm, "nn = ", nn)
    }
    
    

    # 常量声明

    package main
    
    import "fmt"
    
    const (
       // iota是go语言的常量计数器,只能在常量的表达式中使用,默认值为0,每行加1
       BEIJING = iota // 10 * iota = 0 * 10 = 0,下面类推20、30
       SHANGHAI
       SHENZHEN
    )
    
    const (
    	POST = "post"
    	GET = "get"
    )
    
    func main() {
       // 常量(只读)
       const a int = 10
    
       fmt.Println("a = ", a)
    
       fmt.Println("BEIJING = ", BEIJING)
       fmt.Println("SHANGHAI = ", SHANGHAI)
       fmt.Println("SHENZHEN = ", SHENZHEN)
    
    }
    

    # 函数

    # 格式

    func function_name( [parameter list] ) [return_types] {
       函数体
    }
    

    # 单返回值

    func max(num1, num2 int) int {
       /* 声明局部变量 */
       var result int
    
       if (num1 > num2) {
          result = num1
       } else {
          result = num2
       }
       return result
    }
    

    # 多返回值

      package main
      
      import "fmt"
      
      func swap(x, y string) (string, string) {
         return y, x
      }
      
      func main() {
         a, b := swap("Google", "Runoob")
         fmt.Println(a, b)
      }
      
      package main
      
      import "fmt"
      
      // func swap(x, y string) (r1 string, r2 string)
      func swap(x, y string) (r1, r2 string) {
      	r1 = y
      	r2 = x
      	return
      }
      
      func main() {
      	a, b := swap("Google", "Runoob")
      	fmt.Println(a, b)
      }
      
      // Make sure to add code blocks to your code group

      # 导包与 init ()

      image-20221230201349121

        package main
        
        import (
        	"study/5-init/lib1"
        	"study/5-init/lib2"
        )
        
        func main() {
        	lib1.Lib1Func()
        	lib2.Lib2Func()
        }
        
        package lib1
        
        func init() {
        	println("lib1.init")
        }
        
        func Lib1Func() {
        	println("lib1.Lib1Func")
        }
        
        package lib2
        
        func init() {
        	println("lib2.init")
        }
        
        func Lib2Func() {
        	println("lib2.Lib2Func")
        }
        
        // Make sure to add code blocks to your code group

        Go的init()可以理解为Java的静态代码块吗?

        init () 函数在 Go 中有一些特殊的用途,它们是在程序运行期间自动执行的。但是,它们并不完全等同于 Java 中的静态代码块。

        在 Java 中,静态代码块是在类被加载时执行的,并且只会执行一次。这些代码块通常用于初始化类的静态变量。

        在 Go 中,init () 函数也可以用于初始化变量,但它们有一些其他用途:

        • 在 Go 中,init () 函数可以在包中的任何文件中声明,并且在程序运行期间会自动调用。它们不需要被显式地调用,也不需要在任何特定的时间或条件下调用。
        • init () 函数可以在多个文件中声明,并且在程序运行期间会按照它们在源代码中的出现顺序依次调用。这使得它们可以用来确保在程序中的某些部分使用之前已经完成了必要的初始化。
        • init () 函数不能有任何返回值或者参数。

        因此,虽然 init () 函数和 Java 中的静态代码块有一些相似之处,但它们也有一些显著的差异。

        # 安装依赖

        go get -u gorm.io/gorm
        
        • Deprecation of 'go get' for installing executables (弃用 'go get' 来安装可执行文件) - The Go Programming Language (opens new window)

        # 匿名导包与别名

        在一些场景可,可能只想导入某个包触发 init 函数,而不需要执行具体的函数。但 go 是不允许导入包而不适用的,因此如果想要实现这个场景,则需要

        import _ "study/5-init/lib1"
        import . "study/5-init/lib2"
        
        func main() {
        	Lib2Func() // 可以直接使用包中的函数,不需要使用包名
        }
        
        • _ 表示匿名导入,只会触发 init 函数,不会使用包中的其他函数
        • . 表示别名导入,可以直接使用包中的函数,不需要使用包名

        # 指针

        # 没有使用的场景

        package main
        
        import "fmt"
        
        func changeValue(a int) {
        	a = 100
        }
        
        func main() {
        	var a int = 10
        	changeValue(a)
        	fmt.Println(a)
        }
        

        输出结果为 10 ,因为在 changeValue 函数中,a 是一个值拷贝,修改的是 a 的副本,而不是 a 本身

        # 使用指针





         
         




         



        package main
        
        import "fmt"
        
        func changeValue(a *int) {
        	*a = 100
        }
        
        func main() {
        	var a int = 10
        	changeValue(&a)
        	fmt.Println(a)
        }
        

        输出结果为 100 ,因为在 changeValue 函数中,a 是一个指针,修改的是 a 本身

        # defer 语句(类似 finally)

        func main() {
        	defer fmt.Println("defer1")
        	defer fmt.Println("defer2")
        	fmt.Println("main")
        }
        

        输出结果为

        main
        defer2
        defer1
        

        defer的执行顺序

        defer1 先入栈,defer2 后入栈,因此先执行 defer2,再执行 defer1

        • defer 语句会将其后面跟随的语句进行延迟处理。
        • 先执行 return 语句,存储返回值,再执行 defer 语句,最后再返回
        上次更新: 2025/04/17, 14:57:47
        介绍
        集合

        ← 介绍 集合→

        最近更新
        01
        iSCSI服务搭建
        05-10
        02
        磁盘管理与文件系统
        05-02
        03
        网络测试 - iperf3
        05-02
        更多文章>
        Theme by Vdoing | Copyright © 2018-2025 NipGeihou | 友情链接
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式