初识GO:GO语言基础

点击名片关注 阿尘blog,一起学习,一起成长

本文主要分享初次学习GO语言的一些注意事项和基础!

1、GO语言的环境准备和第一个程序:

运行单个编译文件,包名必须是main,go语言的包名和java不一致,可以不与目录一样

环境搭建参考文章

goland开发环境搭建及运行第一个go程序HelloWorld_goland运行go项目-CSDN博客

2、go语言的变量

过语言的变量必须声明

如果声明没有被使用,会报错

不带声明格式的变量不能再函数体外使用,因为不带声明格式的函数是局部变量,只能在声明它们的函数或代码块内部使用。这些变量是自动类型推断的,并且只在当前的函数或代码块内有效。

局部变量优先于全局变量

3、函数后的大括号不能换行

在 Go 语言中,函数体的大括号 {} 通常不会紧跟在函数名后面立即换行,而是与函数名在同一行,这是 Go 语言的常见编码风格。这样做有助于提高代码的可读性,使代码看起来更整洁。

func myFunction() {  
    // 函数体  
    // ...  
}

4、go语言没有三目运算符

三目运算符,也被称为条件运算符,是一种在许多编程语言中常见的运算符,用于根据某个条件的结果选择两个值中的一个。然而,Go语言选择不使用这种运算符,主要是因为Go语言的设计目标之一是保持语法的简洁性和一致性。

5、匿名函数与闭包的关系

匿名函数
匿名函数是没有名称的函数,也称为闭包函数(Closure Function)。它们可以作为一种值被传递,并且可以引用其外部函数的变量。由于它们没有名称,因此不能独立地调用,但可以作为参数传递给其他函数,或者在需要函数值的地方使用。

闭包
闭包是一个函数以及与其相关的引用环境的组合。换句话说,闭包是一个函数,它记住了并访问其词法作用域,即使该函数在其原始作用域之外执行。当一个函数引用了其外部作用域的变量时,就形成了一个闭包。闭包可以访问和控制其外部作用域的变量,即使外部函数已经执行完毕。

关系
在Go语言中,匿名函数是闭包的一种实现方式。当你创建一个匿名函数并引用外部变量时,你就创建了一个闭包。闭包允许函数保留对其词法作用域中变量的引用,并且这些变量在闭包的生命周期内都是有效的。这意味着即使外部函数已经返回,闭包仍然可以访问和修改这些变量。

下面是一个Go语言中匿名函数和闭包的简单示例:

package main  
  
import "fmt"  
  
func main() {  
    x := 10  
  
    // 创建一个匿名函数,并引用外部变量x  
    add := func(i int) int {  
        return x + i  
    }  
  
    // 调用匿名函数  
    fmt.Println(add(5)) // 输出:15  
  
    // 修改外部变量x的值  
    x = 20  
  
    // 再次调用匿名函数,闭包仍然可以访问修改后的x值  
    fmt.Println(add(5)) // 输出:25  
}

在上面的示例中,我们定义了一个匿名函数add,它引用了外部变量x。由于匿名函数引用了外部变量,因此形成了一个闭包。即使main函数中的x值被修改,闭包中的add函数仍然能够访问和使用修改后的x值。

总结来说,匿名函数是闭包的一种实现方式,而闭包是通过引用外部变量形成的函数与其相关引用环境的组合。在Go语言中,匿名函数和闭包常用于实现回调函数、高阶函数和函数式编程等概念。

6、注释:

  1. 单行注释

  • 单行注释以//开头,并持续到该行的末尾。

  • 它通常用于解释代码的功能、目的或实现细节。

  • 示例:// 这是一个单行注释

多行注释

  • 多行注释以/*开头,并以*/结尾。

  • 这种注释方式可以跨越多行,并包含单行注释。

  • 注意,多行注释中不允许嵌套使用多行注释,否则编译器会报错。

  • 示例:/* 这是一个多行注释,可以跨越多行 */

7、命名

Go语言中的函数名、变量名、常量名、类型名、语句标号、和包名都必须以一个字母或下划线开头,GO语言严格区分大小

8、关键字

GO语言的关键字有25个

break      default       func     interface   select
case       defer         go       map         struct
chan       else          goto     package     switch
const      fallthrough   if       range       type
continue   for           import   return      var

此外,还有大约30多个预定义的名字,比如int和true等,主要对应内建的常量、类型和函数。

内建常量: true false iota nil

内建类型: int int8 int16 int32 int64
          uint uint8 uint16 uint32 uint64 uintptr
          float32 float64 complex128 complex64
          bool byte rune string error

内建函数: make len cap new append copy close delete
          complex real imag
          panic recover

9 声明

声明语句定义了程序的各种实体对象以及部分或全部的属性。Go语言主要有四种类型的声明语句:var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明。

一个Go语言编写的程序对应一个或多个以.go为文件后缀名的源文件。每个源文件中以包的声明语句开始,说明该源文件是属于哪个包。包声明语句之后是import语句导入依赖的其它包,然后是包一级的类型、变量、常量、函数的声明语句,包一级的各种类型的声明语句的顺序无关紧要(译注:函数内部的名字则必须先声明之后才能使用)

9.1 变量的声明

声明变量的表达式一般如下::

`var 变量名字 类型 = 表达式``

类型和= 表达式是可以省略的,类型省略将根据初始化表达式太菜变量的类型,如果初始化表达式省略,将默认用对应零值来初始化,避免了报错

GO语言数据类型,默认零值

数据类型默认零值解释
boolfalse布尔类型
int0整数类型,包含(int8,int16,int32,int64)
float0.0浮点数类型(float32、float64)
complex(0+0i)复数类型(complex64、complex128),默认包含实部和虚部
string“”字符串类型,表示文本数据
array数组元素类型的零值 
slicenil切片类型[]T动态数组
pointernil指针类型
mapnil 
struct结构体中每个字段的零值 
interfacenil接口类型
functionnil函数类型
channelnil 

GO可以在个声明语句中同事声明一组变量,或者在一个表达式中声明并初始化一组变量

var i, j, k int                 // int, int, int
var b, f, s = true, 2.3, "four" // bool, float64, string

简短声明

`name := 表达式``

简短声明注意事项:

只能在函数内部使用

不能提供数据类型

声明同时初始化

9.2 变量赋值

直接赋值

var a int
a = 10

声明同时赋值

var b string = "hello"

多重赋值

var d, e int
d, e = 30, 40

简短赋值

c := 20

9.3 匿名变量

匿名变量用__来表示,叫做占位符 或者空标识符,主要用于函数返回值、变量赋值、结构体中的成员等,匿名变量省略了变量名,避免变量名的定义和石笋,减少代码量和命名冲突的可能,匿名变量不分配内存,不会占用内存

使用场景

func test() (int, string) {
    return 10, "hello"
}

x, _ := test()

上面我们用匿名变量来处理忽略不要的变量

type Person struct {
    Name string
    Age int
}

type Student struct {
    Person
    Score float64
}

var s Student
s.Name = "Tom"
s.Age = 18
s.Score = 90.5

在上面的代码中,结构体Student中有一个匿名字段Person,可以通过s.Names.Age来访问Person结构体中的字段。

需要注意的是,在使用匿名变量时,虽然可以省略变量名,但是需要保留变量类型。否则会出现编译错误。

9.4 常量

在Go语言中,常量的定义使用关键字const,常量名一般使用大写字母,多个单词之间使用下划线分隔。常量的值可以是数字、字符串、布尔值等。

const Pi = 3.14159
const Greeting = "Hello, World!"
const MaxInt32 = 1<<31 - 1
const Debug = false

常量还可以使用iota来进行自增,它用于枚举、位运算等场景。iota的初始值为0,每出现一次iota,它的值就自增1。下面是一个枚举的例子:

package main

import "fmt"

const (
    Monday = iota
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
    Sunday
)

func main() {
    fmt.Println(Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday)
}
//0 1 2 3 4 5 6

10 数据类型

基本类型说明
bool布尔型,值为true或false
uint88位无符号整型,取值范围为0到255
uint1616位无符号整型,取值范围为0到65535
uint3232位无符号整型,取值范围为0到4294967295
uint6464位无符号整型,取值范围为0到18446744073709551615
int88位有符号整型,取值范围为-128到127
int1616位有符号整型,取值范围为-32768到32767
int3232位有符号整型,取值范围为-2147483648到2147483647
int6464位有符号整型,取值范围为-9223372036854775808到9223372036854775807
float3232位浮点型,可以表示小数,精度为7位小数
float6464位浮点型,可以表示小数,精度为15位小数
byte8位无符号整型,与uint8相同
rune32位有符号整型,表示一个Unicode码点
uintptr无符号整型,用于存放一个指针的地址
复合类型说明
string字符串类型,由一串Unicode码点组成
array数组类型,元素类型相同,长度固定
slice切片类型,可以动态增长或缩小长度
map映射类型,键值对类型
struct结构体类型,由若干个字段组成,每个字段可以是任意类型
interface接口类型,可以包含任意类型的值
channel通道类型,用于在多个goroutine之间传递数据

go语言的格式化输出 Go语言中的格式化输出是通过fmt包实现的,它支持的格式化动词与C语言中的printf函数类似,但也有一些不同之处。

下面是几个常用的格式化动词及其含义:

%d:将整数格式化为十进制整数。%f:将浮点数格式化为十进制浮点数。%e:将浮点数格式化为科学计数法表示。%s:将字符串格式化为字符串。%v:将值的默认格式表示为字符串。除了动词之外,还可以使用一些修饰符来控制输出格式,如:

%5d:将整数格式化为长度为5的十进制整数。%6.2f:将浮点数格式化为长度为6,保留2位小数的十进制浮点数。下面是一些例子,展示了如何使用格式化输出:

package main

import "fmt"

func main() {
    x := 123
    y := 3.14159
    s := "hello"

    fmt.Printf("x=%d, y=%f, s=%s\n", x, y, s)
    fmt.Printf("x=%5d, y=%6.2f, s=%s\n", x, y, s)
}
x=123, y=3.141590, s=hello
x=  123, y=  3.14, s=hello

在上面的例子中,fmt.Printf函数使用格式化字符串来格式化输出。在格式化字符串中,%d表示整数,%f表示浮点数,%s表示字符串。使用%d和%f时,需要将要输出的值作为参数传递给fmt.Printf函数,使用%s时,直接将要输出的字符串作为参数传递即可。

值得注意的是,使用fmt.Printf函数时,输出格式的字符串和参数列表中的值一一对应,如果不匹配会导致运行时错误。此外,fmt.Printf函数还有其他一些格式化输出相关的函数,如fmt.Sprintf、fmt.Fprintf等,使用方式与fmt.Printf类似。

特殊类型的定义示例

package main

import "fmt"

func main() {
    // 定义一个包含5个整数的数组
    var numbers [5]int

    // 初始化数组
    numbers = [5]int{1, 2, 3, 4, 5}

    // 访问数组元素
    fmt.Println(numbers[2]) // 输出:3

    // 修改数组元素
    numbers[2] = 20
    fmt.Println(numbers) // 输出:[1 2 20 4 5]
}
package main

import "fmt"

func main() {
    // 定义一个初始切片
    numbers := []int{1, 2, 3, 4, 5}

    // 访问切片元素
    fmt.Println(numbers[2]) // 输出:3

    // 修改切片元素
    numbers[2] = 20
    fmt.Println(numbers) // 输出:[1 2 20 4 5]

    // 切片增长
    numbers = append(numbers, 6)
    fmt.Println(numbers) // 输出:[1 2 20 4 5 6]
}
package main

import "fmt"

// 定义一个结构体类型
type Person struct {
    Name string
    Age  int
    City string
}

func main() {
    // 创建一个Person类型的变量
    p := Person{
        Name: "Alice",
        Age:  30,
        City: "New York",
    }

    // 访问结构体字段
    fmt.Println(p.Name) // 输出:Alice
    fmt.Println(p.Age)  // 输出:30
    fmt.Println(p.City) // 输出:New York
}
package main

import "fmt"

func main() {
    // 定义一个映射
    person := make(map[string]int)

    // 向映射中添加键值对
    person["Alice"] = 30
    person["Bob"] = 25

    // 访问映射中的值
    fmt.Println(person["Alice"]) // 输出:30

    // 遍历映射
    for name, age := range person {
        fmt.Printf("%s is %d years old\n", name, age)
    }
}
package main

import "fmt"

func main() {
    // 创建一个通道
    ch := make(chan string)

    // 启动一个goroutine,向通道中发送数据
    go func() {
        ch <- "Hello, Channel!"
    }()

    // 从通道中接收数据
    msg := <-ch

    // 打印接收到的数据
    fmt.Println(msg) // 输出:Hello, Channel!
}
package main

import "fmt"

func main() {
    // 定义一个整数变量
    var num int = 42

    // 获取num的内存地址,并创建一个指向num的指针变量p
    p := &num

    // 使用*操作符来访问指针指向的值
    fmt.Println(*p) // 输出:42

    // 修改指针指向的值
    *p = 100

    // 再次访问num的值,发现它已经被修改
    fmt.Println(num) // 输出:100

    // 指针也可以指向其他类型的变量
    var str string = "Hello, Pointer!"
    strPtr := &str
    fmt.Println(*strPtr) // 输出:Hello, Pointer!

    // 判断指针是否为空
    var nilPtr *int
    fmt.Println(nilPtr) // 输出:nil

    // 使用new函数分配内存并返回指针
    newInt := new(int)
    *newInt = 5
    fmt.Println(*newInt) // 输出:5
}

如果本文有地方遗漏错误,欢迎大家一起交流,仅供参考!

扫描二维码关注阿尘blog,一起交流学习

15178f6fa07fd700404b47acf5329620.png

 

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是阿尘呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值