Go语言语法简记

Hello, World!

package main
import "fmt"
func main() {
    fmt.Println("Hello, World!")
}

数据类型

  • 布尔型:bool
  • 数字类型: int, int8~64, uint, uint8~64, float, float32, float64, complex64, complex128, byte, rune, uintptr
  • 字符串类型:string
  • 派生类型:
    (a) 指针类型(Pointer)
    (b) 数组类型
    ( c ) 结构化类型(struct)
    (d) 函数类型
    (e) 切片类型
    (f) 接口类型(interface)
    (g) Map 类型
    (h) Channel 类型
  • 类型转换
    type_name(expression)

变量

局部变量、全局变量、形参的作用域与C语言类似

package main
var x, y int
var (     // 声明全局变量
    a int 
    b bool
)
var c, d int = 1, 2
var e, f = 123, "hello"

// 这种不带声明格式的只能在函数体中体现
// g, h := 123, "hello"

func main() {
    g, h := 123, "hello"
    println(x, y, a, b, c, d, e, f, g, h)

常量

常量只可以是布尔型、数字型、字符串型

package main

import "fmt"

func main() {
    const LENGHT int = 10
    const WIDTH int = 5
    var area int
    const a, b, c = 1, false, "str"  /// 多重赋值

    area = LENGHT * WIDTH
    fmt.Printf("面积为: %d", area)
    println()
    println(a, b, c)
}

iota特殊常量,自增长

package main

import "fmt"

func main() {
	const (
		a = iota    // 0
		b              // 1
		c		// 2
		d = "ha"	// 独立值, iota += 1
		e		// “ha”      iota += 1
		f = 100	// iota += 1
		g		// 100      iota += 1
		h = iota   // 7
		i		// 8
	}
	fmt.Println(a, b, c, d, e, f, g, h, i)
}

运算符

和C语言运算符用法类似

  • 算术运算符:+ - * / % ++ –

  • 关系运算符:== != > < >= <=

  • 逻辑运算符:&& || !

  • 位运算符:& | ^ << >>

  • 赋值运算符:= += -= *= /= %= <<= >>= &= ^= |=

  • 其他运算符:取地址 &, 指针变量 *

  • 运算符优先级:和C语言差不多

条件语句

if…else if…else

package main

import "fmt"

func main() {
	var a int = 40

	if (a < 20) {
		// 小于20

		if a < 10 {
			// 小于10
		}
	} else if a < 30 {
		// 小于30
	} else {
		// 大于等于30
	}
}		

switch…case

package main 

import "fmt"

func main() {
	var grade string = "B"
	var marks int = 90

	switch marks {
		case 90: grade = "A"
		case 80: grade = "B"
		case 50,60,70: grade = "C"
		default: grade = "D"
	}

	switch {
		case marks == 90 :
			fmt.Printf("优秀!\n")
		case grade == "B", grade == "C" :
			fmt.Printf("良好!\n")
		case grade == "D" :
			fmt.Printf("及格!\n")
		case grade == "F":
			fmt.Printf("不及格!\n")
		default:
			fmt.Print("差!\n")
	}
	fmt.Printf("你的等级是 %s\n", grade)
}

循环语句

for循环有4种形式。for循环可以嵌套。控制语句break, continue, goto语法和C语言一样。

  • for init; condition; post {}
    类似C语言的for

  • for condition {}
    类似C语言的while

  • for {}
    类似C语言的for(; ?

  • for i, x := range array {}
    for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素

例子:

package main 

import "fmt"

func main() {
	var b int = 15
	var a int

	numbers := [6]int{1, 2, 3, 5}

	for a := 0; a < 10; a++ {
		fmt.Printf("a的值为: %d\n", a)
	}

	for a < b {
		a++
		fmt.Printf("a的值为: %d\n", a)
	}

	for i, x := range numbers {
		fmt.Printf("第%d位x的值=%d\n", i, x)
	}
}

函数

函数定义格式如下:
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
}

传地址参数

func swap(x *int, y *int) {
	var temp int
	temp = *x
	*x = *y
	*y = temp
}

函数支持递归调用。函数可以返回多个值。

package main

import “fmt”

func swap(x, y string) (string, string) {
	return y, x
}

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

函数变量

package main

import (
	“fmt”
	"math"
)

func main() {
	/* 声明函数变量 */
	getSquareRoot := func(x float64) float64 {
		return math.Sqrt(x)
	}

	/* 使用函数 */
	fmt.Println(getSquareRoot(9))
}

使用匿名函数做为闭包

package main 

import "fmt"

func getSequence() func() int {
	i := 0
	return func() int {
		i += 1
		return i
	}
}

func main() {
	// nextNumber为一个函数变量, i为0
	nextNumber := getSequence()

	//  每次调用nextNumber函数,i自增1并返回
	fmt.Println(nextNumber()) 
	fmt.Println(nextNumber()) 
	fmt.Println(nextNumber()) 

	// 创建新的函数 nextNumber1, 并查看结果
	nextNumber1 := getSequence()
	fmt.Println(nextNumber1()) 
	fmt.Println(nextNumber1()) 
}

结构体和其方法

package main 

import (
	"fmt"
)

// 定义结构体
type Circle struct {
	radius float64
}

// Circle的方法
func (c Circle) getArea() float64 {
	return 3.14 * c.radius * c.radius
}

func main() {
	var c1 Circle
	c1.radius = 10.00
	fmt.Println("Area of Circle(c1) = ", c1.getArea())
}

数组

数组声明需要指定元素类型及元素个数,语法格式如下:

var variable_name[SIZE] variable_type

例子:

var a [10]float32
var b = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}   // 初始化数组中{}中的元素个数可以小于或等于[]中的数字
var c = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
var d [5][10][4]int
e := [3][4]int{
	{0,1,2,3},
	{4,5,6,7},
	{8,9,10,11}
}

向函数传递数组

func getAverage(arr []int, size int) float32 {
}

遍历数组

package main

import "fmt"

func main() {
	var n [10]int
	var i, j int

	for i = 0; i < 10; i++ {
		n[i] = i + 100
	}

	for j = 0; j < 10; j++ {
		fmt.Printf("Element[%d] = %d\n", j, n[j])
	}
}

指针

package main

import "fmt"

func main() {
	var a int = 20
	var ip *int

	ip = &a

	fmt.Printf(“a变量的地址是:%x\n”, &a)
	fmt.Printf(“ip变量存储的指针地址是:%x\n”, ip)
	fmt.Printf(“ip变量指向地址存储的值是:%d\n”, *ip)
}

空指针判断:

if (ptr != nil) {}
if (ptr == nil) {}

指针数组:

var ptr [10]*int

执行指针的指针变量:

var ptr **int

结构体

结构体变量和结构体指针变量,访问结构体成员都是用点号 .

type Books struct {
	title string
	author string
	subject string
	book_id int
}

var book1 = Books{"Go语言", "Jack", "Go语言教程", 100}

// 也可以使用key : value格式初始化
book2 := Books{title : "Go语言", subject : "Go语言教程", author : "Jack", book_id : 100}

// 忽略的字段为0或空
book3 := Books{title : "Go语言", author : "Jack"}

切片(Slice)

切片是引用类型,是对数组的一个连续片段的引用。多个切片如果引用同一个数组,他们共享同一个数组的内存。
声明切片与声明数组的差别:声明切片时 [ ]中是空的;声明数组时[ ]中有数组长度或者…符号

var identifier []type

例子:

s := []int{1, 2, 3}

// 使用make()函数来创建切片
make([]T, length, capacity)  

// 将数组或者切片arr中从下标startIndex到endIndex-1下的元素创建为一个新的切片
s := arr[startIndex : endIndex]  

举例:

package main

import "fmt"

func main() {
	// 创建数组
	arrays := [...]int{0,1,2,3,4,5,6,7,8}

	// 创建切片number1引用数组arrays
	number1 := arrays[:]

	// 创建切片number2引用数组arrays
	number2 := number1[:]

	// 扩容后,底层创建了新的数组,number1引用了新数组
	number1 = append(number1, 9,10,11)
		
	// 这里只改变了新数组内存的值,arrays数组值没变
	number1[0] = 88
		
	printSlice(number1)
	printSlice(number2)

	// 这里没有改变number2的引用,只是将number1引用的数组值拷贝到number2引用的数组arrays中,超长的部分截断。
	copy(number2, number1)

	printSlice(number2)
	fmt.Println(array[0])  // 88
}

func printSlice(x []int) {
	fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}

范围(Range)

range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。
在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。

package main

import "fmt"

func main() {
	// 使用range求一个slice的和
	nums := []int{2, 3, 4}
	sum := 0
	// 使用空白符"_"忽略了序号
	for _, num := range nums {
		sum += num
	}
	fmt.Println("sum:", sum)

	for i, num := range nums {
		if num == 3 {
			fmt.Println("index:", i)
		}
	}

	// range也可以用在map的键值对上
	kvs := map[string]string{"a" : "apple", "b" : "banana"}
	for k,v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}

	// range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身
	for i, c := range "go" {
		fmt.Println(i, c)
	}
}

Map

通过[ ]插入修改value,通过delete删除键值对

// 声明变量,默认map是nil
var map_variable map[key_data_type]value_data_type

// 使用make函数
map_variable := make(map[key_data_type]value_data_type)

举例:

package main

import "fmt"

func main() {
	// 创建map
	countryCapitalMap := map[string]string{"France" : “Paris”, “Italy" : "Rome", "Japan" : ”Tokyo", "India" : "New delhi"}
	fmt.Println("原始地图")

	// 打印地图
	for contry := range countryCapitalMap {
		fmt.Println(country, "首都是", countryCapitalMap[country])
	}

	// 删除元素
	delete(countryCapitalMap, "France")
	fmt.Println("法国条目被删除")
	
	fmt.Println("删除元素后的地图")
	for country := range countryCapitalMap {
		fmt.Println(country, "首都是", countryCapitalMap[country])
	}
}

接口(Interface)

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

// 定义接口
type interface_name interface {
	method_name1[return_type]
}

// 定义结构体
type struct_name struct {
	// variables
}

// 实现接口方法
func (struct_name_variable struct_name) method_name1() [return_type] {
	// 方法实现
}

例子:

package main

import (
	"fmt"
)

type Phone interface {
	call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
	fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
	fmt.Println("I am iPhone, I can call you!")
}

func main() {
	var phone Phone
	
	phone = new(NokiaPhone)
	phone.call()

	phone = new(IPhone)
	phone.call()
}

Channel

Channel是Go中的一个核心类型,你可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯。
Channel是一个先入先出队列,接收的数据和发送的数据的顺序是一致的。
它的操作符是箭头 <- ,箭头的指向就是数据的流向。

它包含三种类型的定义。可选的<-代表Channel的方向。如果没有指定方向,Channel就是双向的,既可以接收数据,也可以发送数据

chan int       		    // 可以接收和发送类型为int的数据
chan<- float64			// 只可以用来发送float64类型的数据
<-chan int				// 只可以用来接收int类型的数据

使用make初始化Channel,并且可以设置容量:

make(chan int, 100)

容量(capacity)代表Channel容纳的最多的元素的数量,代表Channel的缓存的大小。
如果没有设置容量,或者容量设置为0,说明Channel没有缓存,只有sender和receiver的准备好了后,它们的通讯(communication)才会发生。如果设置了缓存,就有可能不发生阻塞,只有buffer满了后send才会阻塞,而只有缓存空了后receiver才会阻塞。一个nil channel不会通信。

例子:

c := make(chan int)
defer close(c)              // 类似析构函数
go func() { c <- 3+4 } ()   // 创建一个goroutine执行匿名函数
i := <-c
fmt.Println(i)

往一个已经被close的channel中继续发送数据会导致run-time panic。
从一个被close的channel中接收数据不会被阻塞,而是立即返回,接收完已发送的数据后会返回元素类型的零值(zero value)。

错误处理

Go语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义:

type error interface {
	Error() string
}

我们可以在编码中通过实现error接口类型来生成错误信息。
函数通常在最后的返回值中返回错误信息。使用error.New可返回一个错误信息:

func Sqrt(f float64) (float64, error) {
	if f < 0 {
		return 0, errors.New("math: square root of negative number")
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值