golang-语法

参考:https://m.runoob.com/go/

1 最简单的go程序

package main

import "fmt"

func main() {
    fmt.Println("Hello go")
}

go run szj.go //执行szj.go

go build ./ //编译成可执行文件,编译后的文件为文件夹名

go build szj.go //编译成可执行文件,编译后的文件为szj

2 go程序的组成

以上面的示例为例

package main //包声明,每个go项目都必须包含至少一个名为main的包

import "fmt" //导入fmt包

func main() { //程序开始执行的函数,main函数是一个项目所必须包含的。注意:{不能单独放到一行
    fmt.Println("Hello go")
}

3 数据类型

3.1 布尔型

 var b bool = true 

3.2 数字类型

分为整型和浮点型

3.2.1 整型

int8、int16、int32、int64,uint8、uint16、uint32、uint64

3.2.2 浮点型

float32、float64、complex64、complex128

3.3 字符串类型

 

3.4 派生类型

包括:指针类型,数组类型,结构化类型(struct),Channel 类型,函数类型,切片类型,接口类型(interface),Map 类型

3.5 强制类型转换

func main() {
    var sum int = 17
    var count int = 5
    var mean float32

    mean = float32(sum)/float32(count)
    fmt.Printf("mean 的值为: %f\n",mean)
}

 

4 变量

package main
import "fmt"
func main() {
    // 声明一个变量并赋值,注意声明方式:[var 变量名 变量类型 = 变量值]
    var a string = "Runoob"
    fmt.Println(a)
    // 可以一次声明多个变量,并依次赋值。
    var b, c int = 1, 2
    fmt.Println(b, c)
    // 没有初始化就为零值
    var d int
    fmt.Println(d)
    // bool 零值为 false
    var e bool
    fmt.Println(e)
}

 

4.1 值类型和引用类型

值类型:int、float、bool、string属于值类型

其他为引用类型

4.2 :=赋值操作符

声明并初始化变量,我们可以省去var关键字和类型声明,a:=50或b:=false形式定义变量并初始化,这种形式只能用在函数体内。

5 常量

package main
import "fmt"
func main() {
    const LENGTH int = 10 //定义常量,指定数据类型
    const WIDTH = 5 //定义常量,不指定数据类型,由编译器推断
    var area int
    const a, b, c = 1, false, "str" //多重赋值

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

6 运算符

运算符和java类似,下面只介绍几个特殊的运算符

6.1 &和*表示获取变量地址和指针变量

package main
import "fmt"
func main() {
    var a int = 4
    var ptr *int

    ptr = &a     /* 'ptr' 包含了 'a' 变量的地址 */
    fmt.Printf("a 的值为  %d\n", a);
    fmt.Printf("*ptr 为 %d\n", *ptr);
}

>go run szj.go
a 的值为 4
*ptr 为 4

7 函数

使用func定义函数,定义函数格式如下

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)
}

8 数组

声明数组:var 数组名 [数组大小] 数值类型

func main() {
    var balance [5] float32
    fmt.Println(balance)
}

初始化数组

func main() {
    var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    //balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    fmt.Println(balance)
}

如果数组长度不确定,可以使用 ... 代替数组的长度

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

通过指定下标初始化元素

//  将索引为 1 和 3 的元素初始化
balance := [5]float32{1:2.0,3:7.0}

9 指针

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 )
}

运行结果

 

 

空指针,我们使用ptr==nil判断是否为空指针

func main() {
    var  ptr *int
    fmt.Printf("ptr 的值为 : %x\n", ptr)

    if ptr == nil {
        fmt.Printf("ptr是空指针")
    }
}

10 结构体

类似C语言中的结构体

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

func main() {
    // 创建一个新的结构体
    fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
    // 也可以使用 key => value 格式
    fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
    // 忽略的字段为 0 或 空
    fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}

访问结构体成员

func main() {
    var Book1 Books        /* 声明 Book1 为 Books 类型 */

    /* book 1 描述 */
    Book1.title = "Go 语言"
    Book1.author = "www.runoob.com"
    Book1.subject = "Go 语言教程"
    Book1.book_id = 6495407

    /* 打印 Book1 信息 */
    fmt.Printf( "Book 1 title : %s\n", Book1.title)
    fmt.Printf( "Book 1 author : %s\n", Book1.author)
    fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
    fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)
}

结构体作为函数参数

func main() {
    var Book1 Books        /* 声明 Book1 为 Books 类型 */

    /* book 1 描述 */
    Book1.title = "Go 语言"
    Book1.author = "www.runoob.com"
    Book1.subject = "Go 语言教程"
    Book1.book_id = 6495407

    /* 打印 Book1 信息 */
    printBook(Book1)
}

func printBook( book Books ) {
    fmt.Printf( "Book title : %s\n", book.title)
    fmt.Printf( "Book author : %s\n", book.author)
    fmt.Printf( "Book subject : %s\n", book.subject)
    fmt.Printf( "Book book_id : %d\n", book.book_id)
}

结构体指针

func main() {
    var Book1 Books        /* 声明 Book1 为 Books 类型 */

    /* book 1 描述 */
    Book1.title = "Go 语言"
    Book1.author = "www.runoob.com"
    Book1.subject = "Go 语言教程"
    Book1.book_id = 6495407

    /* 打印 Book1 信息 */
    printBook(&Book1)
}
func printBook( book *Books ) {
    fmt.Printf( "Book title : %s\n", book.title)
    fmt.Printf( "Book author : %s\n", book.author)
    fmt.Printf( "Book subject : %s\n", book.subject)
    fmt.Printf( "Book book_id : %d\n", book.book_id)
}

 11 切片

11.1切片创建和初始化

func main() {
    var arr [10]int32 //定义数组
    //arr[0] = 1
    fmt.Println(arr)

    var slice0 []int32 //定义切片
    fmt.Println(slice0)
    
    //var slice1 []int32 = make([]int32, 5) //使用make创建切片并指定长度,并赋值给slice1
    slice1 := make([]int32, 5) //也可简写为这样
    fmt.Println(slice1)
    
    arr2 := [5] int{1,2,3} //数组初始化
    slice2 :=[] int {1,2,3 } //切片初始化
    fmt.Println(slice2)
    slice3 := arr2[:] //通过数组初始化切片
    fmt.Println(slice3)
    slice4 := slice3[1:3] //通过切片A初始化切片B
    fmt.Println(slice4)
}

11.2 len()和cap()

切片长度和容量

func main() {
    var numbers = make([]int,3,5)
    fmt.Printf("len=%d cap=%d slice=%v\n",len(numbers),cap(numbers),numbers)
}

11.3 空(nil)切片

func main() {
    var numbers []int
    if(numbers == nil){
        fmt.Printf("切片是空的")
    }
}

11.4 append()和copy()

func main() {
    var numbers []int
    printSlice(numbers)

    numbers = append(numbers, 2,3,4)
    printSlice(numbers)

    /* 创建切片 numbers1 是之前切片的两倍容量*/
    numbers_two := make([]int, len(numbers), (cap(numbers))*2)

    /* 拷贝 numbers 的内容到 numbers1 */
    copy(numbers_two,numbers)
    printSlice(numbers_two)
}
func printSlice(x []int){
    fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

12 range关键字

作用:用在for循环中迭代数组或map。

迭代数组,返回元素索引和索引对应的值

迭代map,返回key-value对

func main() {
    nums := []int{2, 3, 4}
    sum := 0
    //range用在数组上。我们不需要使用该元素的索引,所以我们使用空白符"_"省略了
    for _, num := range nums {
        sum += num
    }
    fmt.Println("sum:", sum)

    //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)
    }
}

13 go关键字

go关键字用于并发

func main() {
    go reportResult.Run()
    go cycle.Run()
    go temperature.Run()
    go pingpong.Run()
}

 

13 map

声明map方式:map[key数据类型]value数据类型

func main() {
    var countryCapitalMap map[string]string /*创建map */
    countryCapitalMap = make(map[string]string)

    countryCapitalMap [ "France" ] = "巴黎"
    countryCapitalMap [ "Japan" ] = "东京"
    
    for country,capital := range countryCapitalMap {
        fmt.Println(country, "首都是", capital)
    }
}

delete()函数用于删除map中的元素

14 面向对象

我们知道,面向对象的基本特征是抽象,封装,继承和多态

golang使用interface和struct来实现面向对象特性。

14.1 interface(抽象)

我们定义一个接口Phone,里面有一个call方法

定义两个类NokiaPhone和IPhone分别实现这两个接口(注意,golang语法和java语法有比较大的差异)

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()

}

通过如下方式,我们定义了NokiaPhone实现了接口的call方法。

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

注意和函数定义的区别(下面定义了一个无返回值的函数)

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

14.2 封装(struct)

在golang中,我们使用struct封装属性和方法。

下面程序,我们定义了一个类Student,有3个属性name、age、major,1个方法SayHi,1个类似于构造器的方法Init。

注意:在golang中,除slice、map和指针类型属于引用类型外,其他类型都属于值类型。因此我们定义“构造方法”Init时,需要使用指针类型的对象。

属性和方法的公有/私有属性是通过首字母的大小写决定的。比如下例中3个属性是私有的,2个方法是公有的。

type Student struct {
    name  string
    age   int
    major string
}

func (s Student) SayHi() {
    fmt.Printf("Hi, I am %s aged %d, and my major is %s\n", s.name, s.age, s.major)
}

func (s *Student) Init(name string, age int, major string) {
    s.name = name
    s.age = age
    s.major = major
}

func main() {
    s := Student{}
    s.Init("pirlo", 21, "cs")
    s.SayHi()
}

 

 14.3 继承

golang没有显式的继承,golang的继承通过组合实现的

type Person struct {
    name string
    age  int
}

func (p *Person) Init(name string, age int) {
    p.name = name
    p.age = age
}

func (p Person) SayHi() {
    fmt.Printf("Hi, I am %s, %d years old.\n", p.name, p.age)
}

type Employee struct {
    Person
    company string
}

func (e *Employee) Init(name string, age int, company string) {
    e.Person.Init(name, age)
    e.company = company
}

func (e Employee) Work() {
    fmt.Printf("I'm working %s.\n", e.company)
}

func main() {
    p := Person{}
    p.Init("pirlo", 21)
    p.SayHi()

    e := Employee{}
    e.Init("kaka", 22, "milan")
    e.SayHi()
    e.Work()
}

14.4 多态

type Animal interface {
    Move()
    Shout()
}
type Dog struct {
}
type Bird struct {
}
func (dog Dog) Move() {
    fmt.Println("A dog moves with its legs.")
}

func (dog Dog) Shout() {
    fmt.Println("wang wang wang.")
}
func (bird Bird) Move() {
    fmt.Println("A bird flys with its wings.")
}

func (bird Bird) Shout() {
    fmt.Println("A bird shouts.")
}

func main() {
    var animal Animal

    animal = Dog{}
    animal.Move()
    animal.Shout()

    animal = Bird{}
    animal.Move()
    animal.Shout()
}

 

posted @ 2022-03-11 03:39  zhenjingcool  阅读(121)  评论(0编辑  收藏  举报