zoukankan      html  css  js  c++  java
  • go笔记

    时间和日期函数

    1. 时间和日期相关函数,需要导入time包
    2. 获取当前时间 now := time.Now()
    3. 如何获取到其他的日期信息 now.Format()
    4. fmt.Printf(’%d-%d-%d %d:%d:%d’, now.Year(),now.Month(),…)
    5. 格式化日期时间的第二种方式
      fmt.Printf(now.Format(“2006-01-02 15:04:05”))
      fmt.Printf(now.Format(“2006-01-02”))
      fmt.Printf(now.Format(“15:04:05”))
    6. 时间的常量
      const(
      Nanosecond Duration =1 //纳秒
      Microsecond = 1000 * Mi
      Mill

    常量的作用:在程序中可用于获取指定时间单位的时间,比如想得到100毫秒
    7. time.Sleep()
    8. 获取当前Unix时间戳和unixnano时间戳 (可以获取随机的数字)
    9. fmt.Printf(’%v’,now.Unix(),now.UnixNano())

    golang设计者为了编程方便,提供了一些函数,这些函数可以直接使用—内置函数

    1. len
    2. new 用来分配内存,主要用来分配值类型,比如 int,float32,struct 返回的是指针
    3. make 用来分配内存,主要用来分配引用类型 比如channel map slice

    golang错误处理机制

    1) 在默认情况下,当发生错误后(panic),程序就会推出(崩溃)
    2)当发生错误后,可以捕获到错误,并进行处理,保证程序可以继续执行,还可以在捕获到错误后,给管理员一个提示 (邮件,短信)
    3)
    错误处理机制

    1. 1)go语言追求简洁优雅,所以go语言不支持传统的try…catch …finally 这种处理
    2. 2)go中引入的处理方式为defer panic recover
      1. go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。

    错误处理的好处
    进行错误处理后,程序不容易挂掉,如果加入预警代码,就可以让程序更加健壮。

    自定义错误
    go程序中支持自定义错误,使用errors.New和panic内置函数
    1) error.New(“错误说明”) 会返回一个error类型的值,表示一个错误
    2)panic 内置函数,接受一个interface{}类型的值(也就是任何值了)作为参数,可以接受error类型的变量,输出错误信息,并退出程序。、

    数组和切片

    数组可以存放多个同一类型数据,数组也是一种数据类型,在Go中数组是值类型。

    go语言的数组地址是连续的
    数组的各个元素的地址间隔是依据数组的类型决定

    访问数组的元素
    数组名[下标]
    四种初始化数组的方式

    • var newsArray01 [3]int = [3]int {1,2,3}
    • var numsArray02 = [3]int{2,3,3}
    • var numsArray03 = […]int{6,7,8}
    • var names = [3]string{1:“tom”,0:“jack”,3:“marry”}

    数组的遍历
    方一:常规遍历
    方二:for-range 结构遍历
    for index,value := range array01{

    }

    1. 1) 第一个返回值index是数组的下标
    2. 2)第二个value是在该下标位置的值
    3. 3)他们都是仅在for循环内部可见的局部变量
    4. 4)遍历数组元素的时候,如果不想使用下标index,可以直接把index标为下划线_
    5. 5)index 和value的名称不是固定的,即程序员可以自行制定,一般命名为index和value

    数组使用注意事项和细节

    1. 数组是多个相同类型数据的组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化。
    2. var arr []int 这时arr 就是一个slice切片
    3. 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用
    4. 数组创建后,如果没有赋值,有默认值
      数组类型数组,默认值为0
      字符串数组, 默认值为""
      bool数组,默认值为false
    5. 使用数组的步骤,1.声明数组并开辟空间 2.给数组各个元素赋值 3 使用数组
    6. 数组的下标是从0开始的。
    7. 数组下标必须在指定范围内使用,否则报panic,数组越界
      比如 var arr [5]int 则有效下标为0-40
    8. go数组属值类型,在默认情况下是值传递,因此会进行值拷贝。数组间不会相互影响。
    9. 如想在其他函数中,去修改原来的数组,可以使用引用传递(指针方式)
      10.长度是数组类型的一部分,在传递函数参数时需要考虑数组的长度。

    切片 :动态的数组,保存不确定的数组
    切片的基本介绍

    1. 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制
    2. 切片的使用和数组类似,遍历切片,访问切片的元素和求切片长度len(slice)都一样
    3. 切片的长度是可以变化的,切片是一个可以动态变化的数组
    4. 切片定义的语法:
      var 切片名 []类型

    切片的容量是可以动态变化的
    切片容量一般是长度的2倍

    切片在内存中的形式–在内存中如何布局

    • 切片的地址 长度 容量
      从底层来说就是一个数据结构,struct 结构体

    切片使用
    方一:直接使用一个数组,然后用切片
    方二:通过make来切片
    基本语法:var 切片名 []type = make([],len,[cap])

    • 通过make方式创建切片可以指定切片的大小和容量
    • 如果没有给切片的各个元素赋值,那么就会使用默认值(int ,float=>0,string=>’’ bool=>false)
    • 通过make方式创建的切片对应的数组是有make底层维护,对外不可见,即只能通过slice去访问各个元素。
      方三:定义一个切片,直接就指定具体数组,使用原理类似make的方式。

    方一和方二的区别
    方一:直接引用数组,这个数组是先存在的,程序员可见
    方二:通过make来创建切片,make也会创建一个数组,是有切片在底层进行维护程序员不可见。

    切片遍历

    1. for循环常规方式遍历
    2. for-range结构遍历切片

    切片注意事项和细节说明
    切片初始化时 var slice = arr[startIndex:endIndex
    说明: 从arr数组下标为startIndex,取到下标为endIndex的元素(不含arr[endIndex])
    切片初始化,仍然不能越界,范围在[0-len(arr)]之间,但是可以动态增长

    1. 1)var slice = arr[0:end] 可以简写 var slice = arr[:end]
      1. var slice = arr[start:len(arr)] 可以简写var slice = arr[start:]
    2. 3)var slice = arr[0:len(arr)] 可以简写var slice =arr[:]
      cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素
      切片定义完成后,还不能使用,因为本省是一个空的,需要让其引用到一个数组,或者make一个空间供切片来使用
      切片可以继续切片
      用append函数,可以对切片进行动态追加
      切片的拷贝操作,切片使用copy内置函数完成拷贝。

    string 和slice

    1. string底层是一个byte数组,因此string也可以进行切片处理。
    2. string 和切片在内存的形式
    3. string是不可变的,也就是说不能通过str[0] = ‘z’ 方式来修改字符串
    4. 如果需要修改字符串,可以先将string->[]byte/或者[]rune->修改->重写转成string

    排序和查找

    • 内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序。
      (包括交换式排序法,选择式排序法和插入式排序法)
    • 外部排序法 数据量过大,无法全部加载到内存中,需要借助外部存储进行排序,
      (合并排序法和直接合并排序法)
      交换式排序法:
    1. 冒泡排序法
    2. 快速排序法

    MAP

    map是key-value数据结构,又称为字段或者关联数组,类似其他编程语言的的集合

    var map变量名 map[keytype]valuetype
    key 可以是什么类型
    go中map的key可以是很多类型,比如bool,数字,string,指针,chanel ,还可以包含前面几个类型的接口,结构体,数组,
    通常为int string

    注意 slice,map还有function不可以作为key,因为这几个没法用==来判断

    valuetype的类型和key基本一行,
    通常是数字(整数,浮点数)string struct

    生命是不会分配内存的,初始化需要make,分配内存后才能赋值和使用

    map总结的几点

    1. map在使用前一定要make
    2. map的key是不能重复的,如果重复了,则以最后这个key-value为准
    3. map的value是可以相同的
    4. map的key-value是无序的。

    map 使用细节

    1. map是引用类型,遵守引用类型传递的机制,再一个函数接受map,修改后,会直接修改原来的map
    2. map的容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长键值对(key-value)
    3. map的value也经常使用struct类型,更适合管理复杂的数据

    go面向对象编程说明

    1. 1)go支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言,所以我们说golang支持面向对象编程特性是比较准确的。
      1. go中没有类class,go语言的结构体和其他编程语言的类有同等地位,go是基于struct来实现oop特性的。
    2. 3)go面向对象编程非常简洁,去掉了传统OOP语言的继承,方法重载,构造函数和析构函数,隐藏的this指针等
    3. 4)go仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其他OOP语言不一样,比如继承,go中没有extend关键字,继承是通过匿名字段来实现的。
    4. 5)go面向对象很优雅,oop本身就是语言类型系统(type system)的一部分,通过接口关联,耦合性低,非常灵活,go中面向接口编程

    结构体注意细节
    1.结构体的所有字段在内存中是连续的
    指针本身的地址还是连续的,但是指针指向的地址不一定时连续的。
    2.结构体是用户单独定义的类型,和其他类型进行转换时需要有完全相同的字段(名字,个数和类型)
    3.结构体进行type重新定义(相当于取别名)golang认为是新的数据类型,但是相互间可以强转
    4.struct的每个字段上,可以写一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和反序列化

    struct方法
    go中的方法是作用在指定的数据类型上的(和指定的数据类型绑定)。因此自定义类型,都可以有方法,而不仅仅是struct.


    方法的声明
    func (recevier type)methodName (参数列表)(返回值列表){
    方法体
    return 返回值
    }

    1. 参数列表 表示方法输入
    2. recevier type 表示这个方法和type这个类型进行绑定,或者说该方法作用域type类型
    3. recevier type type可以是结构体,也可以其他的自定义类型
    4. receiver:就是type类型的一个变量(实例),比如Person结构体的一个变量(实例)
    5. 参数列表:表示方法输入
    6. 返回列表:表示返回的值,可有多个
    7. 方法主体:表示为了实现某一功能代码块
    8. return 语句不是必须的。

    方法的注意事项和细节讨论 重要

    1. 结构体类型是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝传递方法
    2. 如程序员希望在方法中,修改结构体变量的值,可以通过结构体指针的方式来处理。
    3. go中的方法作用在指定的数据类型上,即(和指定的数据类型绑定)。因此自定义类型,都可以有方法,而不仅仅是struct,比如int,float32 等都可以有方法。
    4. 方法的访问范围控制规则,和函数一样,方法名首字母小写,只能在本包访问,方法首字母大写,可以在本包和其他包访问
    5. 如果一个变量实现了string()这个方法,那么fmt.Println()默认会调用这个变量的string()进行输出

    方法和函数区别

    1. 调用方式不一样
      函数的调用方式 : 函数名(实参列表)
      方法的调用方式:变量名.方法名(实参列表)

    2. 对于普通函数,接受者为值类型时,不能讲指针类型的数据直接传递,反之亦然。

    3. 对于方法(比如struct方法)接受者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以。

    总结:

    1. 不管调用形式如何,真正决定是值拷贝还是地址拷贝,看这个方法是和那个类型绑定。
    2. 如果是和值类型,比如(P,Person)则是值拷贝,如果和指针类型,比如是(p *Person)则是地址拷贝。

    面向对象编程应用实例
    步骤

    1. 声明(定义)结构体,确定结构体名。
    2. 编写结构体的字段
    3. 编写结构体的方法

    面向对象编程-抽象
    面向对象三大特性:封装 继承 多态
    go中没有特别强调封装,
    继承可以解决代码复用,当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法。
    其他的结构体不需要重新定义这些属性和方法,只需要嵌套一个Student匿名结构体即可。
    也就是说,在go中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。

    嵌入一个匿名结构体实现继承,
    继承的深入讨论、

    1. 1)结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段,方法,都可以使用
    2. 2)匿名结构体字段访问可以简化
    3. 3)当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分。
    4. 4)结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有相同的字段和方法)在访问时,就必须明确指定匿名结构体名字,否则编译器报错。
    5. 5)如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段和方法时,必须带上结构体的名字。
    6. 6)嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。

    多重继承

    • 如一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。
    • 为了保证代码的间接性,建议不要使用多重继承

    接口 interface 减少耦合 松耦合 高类聚

    go中 多态特性主要是通过接口来体现的
    基本介绍

    • interfaceleixi8ng可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量,到某个自定义类型(比如结构体Phone)要使用的时候,再根据具体情况把这些方法写出来。
      基本语法
      type 接口名 interface{
      method1 (参数列表)返回值列表
      method2 (参数列表) 返回值列表
      }
      func (t 自定义类型) method(参数列表) 返回值列表{
      //方法实现
      }
      说明
    1. 接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法,接口体现了程序设计的多态和高内聚低耦合的思想。
    2. go中的接口,不需要显示的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口,go中没有implement这样的关键字。

    接口的注意事项和细节

    1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义的变量(实例)
    2. 接口中的所有方法都没有方法体,即都是没有实现的方法
    3. 在go中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口
    4. 一个自定义类型只能实现了某个接口,才能将该自定义类型的实例(变量)赋给接口的类型
    5. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
    6. 一个自定义类型可以实现多个接口
    7. go接口中不能有任何变量
    8. 一个接口(比如A接口)可以继承多个别的接口(比如 B接口,C接口)这时如果要实现A接口,也必须将B,C接口的方法也全部实现。
    9. interface类型默认是一个指针(引用类型)如果没有对interface初始化就使用,那么会输出nil
    10. 空接口interface{}没有任何方法,所以所有类型都实现了空接口

    go基于函数(方法)实现。

    接口和继承的关系

    1. 当A结构体继承了B结构体,那么A结构就自动的继承了B结构体的字段和方法,并且可以直接使用
    2. 当A结构体需要扩展功能,同时不希望去破坏继承关系。

    实现接口可以看做是对继承的一种补充

    1.接口和继承解决的问题不同
    继承的价值主要在于:解决代码的复用性和可维护性
    接口的价值主要在于:设计,设计好各种规范(方法),让其它自定义类型去实现这些方法
    2. 接口比继承更加灵活
    接口比继承更加灵活,继承是满足is-a的关系,而接口只需要满足like-a的关系。
    3. 接口在一定程度上实现代码解耦

    面向对象的多态
    变量(实例)具有多种形态,
    go语言中,多态是通过接口实现的。可以按照统一的接口来调用不同的实现,这时接口变量就呈现不同的形态。

    golang 在创建结构体实例(变量)时,可以直接指定字段的值。
    创建结构体变量时指定字段值方式

    1. 方一:
      var stu1 Student = Student{“tome”,10}
      stu2 := Student{“tom”,10}
    2. 方二
      var stu *Student = &Student{“smith”,20}
      var stu2 *Student = &Student{}

    go 工厂模式
    golang的结构没有构造函数,,通常可以使用工厂模式来解决这个问题。

    使用工厂模式实现跨包创建结构体实例(变量)的案例
    如果model包的结构体变量首字母大写,引入后,直接使用,没有问题。
    如果model包的结构体变量首字母小写,引入后,不能直接使用,可以工厂模式解决。

    文件的基本介绍
    文件是数据源(保存数据的地方)
    文件在程序中是以流的形式来操作的,
    打开文件的方法 Open 关闭文件的路径Close
    os 包 Variable
    os.Args是一个string的切片,用来存储所有的命令行参数。
    go中的json
    json (javascript object notation )是一种轻量级的数据交换格式,易于人阅读和编写,同事也易于机器解析和生成。

    类型断言,由于接口是一般类型,不知道具体类型,
    如果要转成具体类型,就需要使用类型断言。

  • 相关阅读:
    #转 并查集详解
    美素数
    Wireless Network
    寒假CF- WA了不要怕!
    寒假CF1 小呀小苹果儿
    (专题赛)A Bug's Life
    (周三赛)The Hardest Problem Ever
    (周三赛)A==B?
    (周三赛)还是畅通工程
    cursor改变鼠标样式
  • 原文地址:https://www.cnblogs.com/liuqun/p/12655170.html
Copyright © 2011-2022 走看看