go语言基础

 : jank    :   : 2324    : 2016-10-25 16:43  go

go语言学习笔记:


2016 10/13

1.go语言环境安装:

下载:wget https://storage.googleapis.com/golang/go1.7.1.linux-amd64.tar.gz

解压到/usr/local/go中

配置path环境

vim /etc/profile

export PATH=$PATH:/usr/local/go/bin

source /etc/profile


2.go语言基本语法

package main //引入main包
import "fmt"
func main(){
fmt.Println("hello, world!")    //需要使用双引,结束无需加';', println会自动换行
fmt.Print("hello, jank")  //输出不换行
}

3.定义变量

    var name string
var a = "jank"
var b string = "10"
var c, d, e = "liberalist", 100, "jank" //定义多个变量
f := "jason"    //这种不带声明格式的只能在函数体中实现
var (
g int   //主要用去全局变量
)

4.定义常量

   1.const常量

const length = 10

const width int = 20

const(//做枚举

              aa = "abc"

              bb = 100

)

//常量可以用len(), cap(), unsafe.Sizeof()常量计算表达式的值。

//常量表达式中,函数必须是内置函数,否则编译不过,例:

package main
import "unsafe"
const (
    a = "abc"
    b = len(a)
    c = unsafe.Sizeof(a)
)
func main(){
    println(a, b, c)
}

2.iota,特殊常量,可以认为是一个可以被编译器修改的常量。

在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,

每出现一次iota,其所代表的数字会自动增加1。

iota 可以被用作枚举值:

const (
    a = iota      //0
    b = iota      //1
    c = iota      //2   
)

第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;

所以 a=0, b=1, c=2 可以简写为如下形式:

const (
    a = iota      //0
    b             //1
    c             //2
    d = 100       //100
    e             //4
    f = iota      //5
)

5.运算符

go语言的普通运算符和php的普通运算符基本一致。

6.条件语句

   1. if语句与php中的if基本一致。但不需要加小括号

   2. go语言中的switch语句,相比php switch不需要加小括号,每一个条件没有break

       var a='jank'
       var b string
       switch a{
       case 'jack': b = 'jack li'
       case 'jank': b = 'jank ai'
       default :
           b = 'nobody'
       }


      php中:

    $a = "jank";
    switch($a){
        case "jack": $b = "jack li";
            break;
        case "jank": $b = "jank ai";
            break;
        default :
            $b = "nobody";
            break;
    }
    echo $b;

   3. select语句

   select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,

   要么是发送要么是接收。select随机执行一个可运行的case。

如果没有case可运行,它将阻塞,直到有case可运行。也有default默认。

7.循环语句

package main
import "fmt"
func main(){
var b int = 15
var a int
numbers := [6]int{1, 2, 3, 5} 
/* for 循环 */
for a = 0; a < 10; a++ {
fmt.Printf("a 的值为: %d
", a) //%d空格
if a == 
}
for a < b {
a++
fmt.Printf("a 的值为: %d
", a)
}
for i,x:= range numbers {
fmt.Printf("第 %d 位 x 的值 = %d
", i,x)
}   
}

go语言中的break和continue同php一致


8.go语言函数

1. 语法:最少有一个main函数,其他的可以自定义,

func function_name(传参 参数type) return_type{

   //函数体

}

return_type 指的是函數調用返回值的類型,其中返回幾個值就得有幾個類型如:(int,string,int)

2.閉包

   闭包是由函数和与其相关的引用环境组合而成的实体。比如参考资源中就有这样的的定义:

   在实现深约束(注2)时,需要创建一个能显式表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体被称为闭包。

   例:

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


3.方法:

Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。语法格式如下:

func (variable_name variable_data_type) function_name() [return_type]{
   /* 函数体*/
}
package main
import (
   "fmt"  
)
/* 定义函数 */
type Circle struct {
  radius float64
}
func main() {
  var c1 Circle
  c1.radius = 10.00
  fmt.Println("Area of Circle(c1) = ", c1.getArea())
}
//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
  //c.radius 即为 Circle 类型对象中的属性
  return 3.14 * c.radius * c.radius
}

9.数组

1. 声明数组

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

var variable_name [SIZE] variable_type

例:


package main
import "fmt"
var jank [3]int  //int 指的是键的类型
var i int
func main(){
    for i=0; i<3; i++{
        jank[i] = i + 100;
    }
    for i=0; i<3; i++{
        fmt.Println(jank[i]);
    }
}

2. 二维数组

二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:

var arrayName [ x ][ y ] variable_type

例:

package main
import "fmt"
var jank [2][3]int
var i,j int
func main(){
    for i=0; i<2; i++{
         for j=0; j<3; j++{
             jank[i][j] = j + 100;
         }
    }
    for i=0; i<2; i++{
        for j=0; j<3; j++{
            fmt.Println("jank[",i,"][",j,"]",jank[i][j]);
        }
}
}

3.数组传参

例:


func getAverage(arr []int, size int) float32 {
   var i,sum int
   var avg float32  
   for i = 0; i < size;i++ {
      sum += arr[i]
   }
   avg = float32(sum / size)
   return avg;
}


10.指针

1. 一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。

类似于变量和常量,在使用指针前你需要声明指针。

2. 定义指针、获取指针的位置、获取指针的值

var n = "jank"

var name *string

name = &n

fmt.Println("获取指针的位置:", $name)

fmt.Println("获取指针的值:", *name)

3. go空指针为 nil

4. 指针数组

package main
import "fmt"
const MAX int = 3
func main() {
   a := []int{10,100,200}
   var i int
   var ptr [MAX]*int;
   for  i = 0; i < MAX; i++ {
      ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
   }
   for  i = 0; i < MAX; i++ {
      fmt.Printf("a[%d] = %d
", i,*ptr[i] )
   }
}

5. 指向指针的指针

1. 如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。

当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址。

2. 指向指针的指针变量为整型 var ptr **int;

访问指向指针的指针变量值需要使用两个 * 号


6. 函数调用指针

package main
import "fmt"
func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int= 200
   fmt.Printf("交换前 a 的值 : %d
", a )
   fmt.Printf("交换前 b 的值 : %d
", b )
   swap(&a, &b);
   fmt.Printf("交换后 a 的值 : %d
", a )
   fmt.Printf("交换后 b 的值 : %d
", b )
}
func swap(x *int, y *int) {
   var temp int
   temp = *x    /* 保存 x 地址的值 */
   *x = *y      /* 将 y 赋值给 x */
   *y = temp    /* 将 temp 赋值给 y */
}

    11.go语言结构体

    1. 定义结构体

    结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,

    结构体有中一个或多个成员。type 语句设定了结构体的名称。

    2.访问结构体

    访问结构体成员,需要使用点号'.'操作符,格式为:"结构体.成员名"。

结构体类型变量使用struct关键字定义


例:

package main
import "fmt"
type Book struct {
title string
auther string
age int
}
func main() {
var Book1 Book //声明Book1 为Book类型
    Book1.title = "liberalist"
    Book1.auther = "jank"
    Book1.age = 2023
    fmt.Println(Book1.age) //打印age
    printBook(Book1) //函数传参调用
}
func printBook(book Book){ //函数定义
fmt.Println(book.title)
}

3. 结构体指针

    package main
import "fmt"
type Book struct {
title string
auther string
age int
}
func main() {
var Book1 Book //声明Book1 为Book类型
    Book1.title = "liberalist"
    Book1.auther = "jank"
    Book1.age = 2023
    printBook(&Book1) //函数传参调用指针
}
func printBook(book *Book){ //函数定义
fmt.Println(book.title)
}

12.go语言切片

1. Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,

       功能强悍的内置类型切片("动态数组")与数组相比切片的长度是不固定的,

       可以追加元素,在追加时可能使切片的容量增大。

        切片不需要说明长度。

        2. len() 和 cap() 函数

切片是可索引的,并且可以由 len() 方法获取长度。

切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

以下为具体实例:

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

以上实例运行输出结果为:

len=3 cap=5 slice=[0 0 0]

3. 空(nil)切片。一个切片在未初始化之前默认为 nil,长度为 0,

4. 切片截取

  /* 创建切片 */

  numbers := []int{0,1,2,3,4,5,6,7,8}   

  printSlice(numbers)

  /* 打印原始切片 */

  fmt.Println("numbers ==", numbers)

  /* 打印子切片从索引1(包含) 到索引4(不包含)*/

  fmt.Println("numbers[1:4] ==", numbers[1:4])

  /* 默认下限为 0*/

  fmt.Println("numbers[:3] ==", numbers[:3])

  /* 默认上限为 len(s)*/

  fmt.Println("numbers[4:] ==", numbers[4:])

5. append() 和 copy()

   /* 允许追加空切片 */

   numbers = append(numbers, 0)

   printSlice(numbers)

   /* 向切片添加一个元素 */

   numbers = append(numbers, 1)

   printSlice(numbers)

   /* 同时添加多个元素 */

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

   printSlice(numbers)


   /* 创建切片 numbers1 是之前切片的两倍容量*/

    numbers1 := make([]int, len(numbers), (cap(numbers))*2)

   /* 拷贝 numbers 的内容到 numbers1 */

   copy(numbers1,numbers)

   printSlice(numbers1)   

13.Go 语言范围(Range)

        1. Go 语言中 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)
    //在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
    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
", k, v)
    }
    //range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
    for i, c := range "go" {
        fmt.Println(i, c)
    }
}

14.Go 语言Map(集合)

1. Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

package main
import "fmt"
func main() {
    var countryCapitalMap map[string]string
    /* 创建集合 */
    countryCapitalMap = make(map[string]string)
    /* map 插入 key-value 对,各个国家对应的首都 */
    countryCapitalMap["France"] = "Paris"
    countryCapitalMap["Italy"] = "Rome"
    countryCapitalMap["Japan"] = "Tokyo"
    countryCapitalMap["India"] = "New Delhi"
    /* 使用 key 输出 map 值 */
    for country := range countryCapitalMap {
        fmt.Println("Capital of",country,"is",countryCapitalMap[country])
    }
    /* 查看元素在集合中是否存在 */
    captial, ok := countryCapitalMap["United States"]
    /* 如果 ok 是 true, 则存在,否则不存在 */
    if(ok){
        fmt.Println("Capital of United States is", captial)  
    }else {
        fmt.Println("Capital of United States is not present") 
    }
}

以上实例运行结果为:

Capital of France is Paris

Capital of Italy is Rome

Capital of Japan is Tokyo

Capital of India is New Delhi

Capital of United States is not present

2. delete() 函数

delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。实例如下:

例:

package main
import "fmt"
func main() {   
   /* 创建 map */
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}
   fmt.Println("原始 map")   
   /* 打印 map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
   /* 删除元素 */
   delete(countryCapitalMap,"France");
   fmt.Println("Entry for France is deleted")  
   fmt.Println("删除元素后 map")   
   /* 打印 map */
   for country := range countryCapitalMap {
      fmt.Println("Capital of",country,"is",countryCapitalMap[country])
   }
}

15.go递归

1. 斐波那契数列

以下实例通过 Go 语言的递归函数实现斐波那契数列:

package main
import "fmt"
func fibonaci(n int) int {
    if n < 2 {
        return n
    }
    return fibonaci(n-2) + fibonaci(n-1)
}
func main() {
    var i int
    for i = 0; i < 10; i++ {
       fmt.Printf("%d	", fibonaci(i))
    }
}

16.go语言类型转换 

格式: type("值")

例:

var a int = 17
var b int = 3
var age float32
age = float32(a) / float32(b)
fmt.Println(age)

17,Go 语言接口

1. Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,

任何其他类型只要实现了这些方法就是实现了这个接口。

例:

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



   

备案编号:赣ICP备15011386号

联系方式:qq:1150662577    邮箱:1150662577@qq.com