golang

yuerumylove · · 471 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

go变量
// 变量可以以字母,数字,下划线组成,但是只能以数字或下划线开头
var varibale type = value
var varuable = value // 根据值类型自动推断类型
var variable_1 type
variable_1 = value
// 1. 已经声明的变量不能使用以下方式赋值。:= 左侧的变量不应该时已经被声明过的。
// 2. 同时不带声明格式的只能在函数体中出现。
// 3. 使用:= 赋值的变量不能再次使用:=赋值。否则 提示编译错误:no new variables on left side of :=
// 4.go中如果你声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误。a declared and not used.
// 5. 全局变量允许声明但不使用。
// 6.如果想要交换两个变量的值,可以简单使用a, b = b, a
// 空白标识符 _ 用于弃值。他实际上是一个只写变量,你不能得到它的值。常用于函数返回时不需要使用。
variable_2 := value
var vn1, vn2, vn3 = value // 多个变量
// 这中方式一般用于声明全局变量
var (
  vname1 type
  vname2 type 
)

变量的作用域:
全局变量和局部变量:局部变量的名称可以和局部变量相同,会根据就近原则使用:

初始值:
int/float 0
pointer nil

go常量
// 常量使用关键字const声明,常量可以不被使用
const vn [type]  = value
// 1. iota是一个特殊的值,可以认为是一个可以被编译器修改的常量,iota在关键字出现时被置为0.每当iota在新的一行被使用时,都会自动加1.
// 2.常量为被赋值时,将自动使用上一行已赋值的值
// 3.常量可以使用表达式len,cap unsafe.sizeof等赋值,但是只能使用内置函数。
const(
  e = 0
  f
  g
)
const (
    a = iota
    b = iota
    c = iota
)
go运算符
// 算术运算符: 
+ - * / % += --
// 关系运算符:
==  !=  < > >= <=
// 逻辑运算符:
&& || ! 
// 位运算符:    
& | ^ << >>
// 赋值运算符:
= += -= *= %= <<= >>= &= ^= |=
// 其他:
 & 返回变量地址
 * 指针变量
// 优先级:
! ^
* / % >> << & &^
+ - | ^
== != < <== >= > 
<-
&&
||
go条件语句和循环语句(for)
// if条件语句,与其他语言不同,go的if判断语句不需要括号即可
var a  = 1
if a == 1 {
  fmt.Println("a = ", a)
}
// switch-case语句:
// 1. 可以在switch语句中判断x的类型。只能在switch中使用
// 2. default可选
// 3. fallthrough强制执行下一条语句.判断类型时不能用fallthrough;fallthrough不能用在最后一个case语句;fallthrough从第一个case正确的语句开始生效
// 4. 可选break。默认每个语句自带break
// 5. case语句中不能有多个重复条件:duplicate case
// 6. case语句中可以判断多个条件
// 7. switch不指定内容,case指定true,false时,case条件可以重复
 var x interface{}
 switch i := x.(type) {
      case nil:   
         fmt.Printf(" x 的类型 :%T",i)                
      case int:   
         fmt.Printf("x 是 int 型")                       
      case float64:
         fmt.Printf("x 是 float64 型")           
      case func(int) float64:
         fmt.Printf("x 是 func(int) 型")                      
      case bool, string:
         fmt.Printf("x 是 bool 或 string 型" )       
      default:
         fmt.Printf("未知型")     
   }   
// select语句。select随机执行一个可运行的case。如果没有可运行的case,它将阻塞。知道case可运行。
// 每个case都必须是一个通信
// 所有channel表达式都会被求值
// 所有被发送的表达式都会被求值
// 如果任意某个通信可以进行,它将执行,其他被忽略。
// 如果有多个case可运行,select会随机公平的选出一个运行,其他不会执行。
// 如果有default自居,则执行该语句。
// 如果没有default子句。select将阻塞。直到某个通信可以运行。go不会重新对channel或值进行求值。
var c1, c2, c3 chan int
   var i1, i2 int
   select {
      case i1 = <-c1:
         fmt.Printf("received ", i1, " from c1\n")
      case c2 <- i2:
         fmt.Printf("sent ", i2, " to c2\n")
      case i3, ok := (<-c3):  // same as: i3, ok := <-c3
         if ok {
            fmt.Printf("received ", i3, " from c3\n")
         } else {
            fmt.Printf("c3 is closed\n")
         }
      default:
         fmt.Printf("no communication\n")
   }    
// 循环语句:同基本的循环语句 
// 可以使用goto语句,continue, break等
t := 1
for t < 20 {
  fmt.Println("t = ", t)
  t++
}

// sample goto
var a int = 10

   /* 循环 */
   LOOP: for a < 20 {
      if a == 15 {
         /* 跳过迭代 */
         a = a + 1
         goto LOOP
      }
      fmt.Printf("a的值为 : %d\n", a)
      a++     
   }  
go值类型和引用类型
// 值类型:变量直接存储值,内存通常在栈中分配,栈在函数调用完后会释放
int 
float
bool
string
array
struct
// 引用类型:变量存储的是一个地址,这个地址存储最终的值,内存通常在堆上分配。通过GC回收
// 指针 
pointer
slice
map
chan 
go的内存管理

参考:https://www.jianshu.com/p/47691d870756

go函数(go函数默认是值传递)
// 参数类型相同,多个返回值
func maxNew(n1, n2 int) (int, error)
// 参数类型不同
func swap(x string, y int) int
// go函数默认是值传递,如果要使用引用传递,需要使用指针
func swap(x, y *int) 
// go的闭包:
func cmpAndPrint() (func(n int), func(n int)){
    compare := 20
    return func(n int){
        if n > compare {
            fmt.Println("n is largger than 20")
        }
    }, func(n int) {
        if n < compare {
            fmt.Println("n is smaller than 20")
        }
    }
}

关于go的闭包,网上非常好的例子:
https://www.cnblogs.com/cxying93/p/6103375.html
https://www.cnblogs.com/hzhuxin/p/9199332.html

闭包就是外部函数能够访问函数内部的变量。根本上说是为了函数内外进行沟通。
闭包的用处有两个:
-可以读取函数内部的变量
-另一个是让这些变量的值始终保持在内存中,不会在函数被调用后被自动清除。

闭包注意点:
  1. 闭包会使得函数中的变量都被保存在内存中,内存消耗很大。所以不能滥用闭包。否则会造成性能问题。
  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值
指针变量

var var_name *var-type

var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。以下是有效的指针声明:

var ip int / 指向整型*/
var fp float32 / 指向浮点型 */

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。

var a int = 20
var ip int
fmt.Printf("
ip 变量的值: %d\n", *ip ) // 20

当一个指针被定义后没有分配到任何变量时,它的值为nil。nil成为空指针。

go for 循环指针异常:
go在for循环中,不论是普通的for循环,还是range循环,每次分配给变量的值总是保存在一个固定的地址上,这就会导致我们使用指针时,得到的指针数组的是相同的。如例:

    for ins := 0; ins < len(arr); ins++ {
        fmt.Println("=========", &ins)
        // newarr = append(newarr, arr[ins])
        newarr = append(newarr, ins)
        // ptrlist[ins] = &arr[ins]
        ptrlist = append(ptrlist, &ins)
    }

    for _, ptr := range ptrlist {
        fmt.Println(ptr)
        fmt.Println(*ptr)
    }

结果示例:
========= 0xc000056330
========= 0xc000056330
========= 0xc000056330
========= 0xc000056330
========= 0xc000056330
0xc000056330
5
0xc000056330
5
0xc000056330
5
0xc000056330
5
0xc000056330
5

指针的指针:
**ptr

go的切片

未指定大小的数组作为切片:
切片不需要说明长度,类似java中的Collection集合,或使用make函数来创建切片。

var identifier []type

var slice1 []type = make([]type, len)
// 也可以简写为
slice1 := make([]type, len)

常用函数:

len()
cap()
append()
copy()
go range

语法

// 切片
for i, num := range nums {
        if num == 3 {
            fmt.Println("index:", i)
        }
  }
// map
//range也可以用在map的键值对上。
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
    fmt.Printf("%s -> %s\n", k, v)
}
go map
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
go接口完整示例
package main

import "fmt"

func main() {

    samsungPhone := samsung{"samsugn", "qua", "2440 * 1680", 312315456, []string{"zhangsan", "list"}}
    samsungPhone.call(samsungPhone.phonenumber, samsungPhone.contractors[0])
}

type mobile interface {

    call(number int64, man string) int64

    play(game string)
}

type samsung struct {
    brand string
    cpu string
    film string
    phonenumber int64
    contractors []string
}

func (samsungPhone samsung) call(number int64, man string)  {
    fmt.Println(samsungPhone.brand, "call ", man, " at ", number)
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:yuerumylove

查看原文:golang

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

471 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传