zoukankan      html  css  js  c++  java
  • Go的基本数据类型

    这是 Go 学习笔记的第一篇,主要是 Go 基本数据类型的学习总结。
    由于本人一直使用 PHP 语言进行开发,在学习 Go 的过程中发现有些知识点经常混淆,遂将 Go 与 PHP 做了比较(仅限于二者的基本数据类型)。
     
    Go
    PHP
    基本数据类型
    布尔型
    数字类型:
    • 整型(int、unit)
    • 浮点型(float32、float64)
    • 其它:byte(类似unit8)、rune(类似int32)等
    字符串类型
    派生类型:
    • 指针类型(Pointer)
    • 数组类型(Array)
    • 结构类型(Struct)
    • 管道类型(Channel)
    • 函数类型(Function)
    • 切片类型(Slice)
    • 接口类型(Interface)
    • Map类型(Map)
    4 种标量类型:
    • boolean(布尔型)
    • integer(整型)
    • float(浮点型,也称作 double)
    • string(字符串)
    3 种复合类型:
    • array(数组)
    • object(对象)
    • callable(可调用)
    2 种特殊类型:
    • resource(资源)
    • NULL(无类型)
    字符串
    字节编码
    • 字符串的字节默认使用 UTF-8 编码
    • 支持 Unicode 字符
    • 只支持 256 的字符集,需要在代码中显式指定字符编码 header("Content-Type: text/html;charset=utf-8"); 或修改php.ini中有关默认字符集的设置 default_charset = "utf-8" 
    • 不支持 Unicode 字符
    字符串定义
    • 双引号(""):双引号中的转义字符会被替换
    • 反引号(``):反引号中原生字符串中的转义字符(如 )会被原样输出
    • 单引号(''):单引号括起来的单个字符,需要格式化输出,%c,否则输出字符码数
    • 双引号(""):双引号中的转义字符会被替换,可以解析变量,即将变量包含在双引号中
    • 单引号(''):与Go的反引号类似,转义字符不会被转义,原样输出
    字符串长度

     len() :获取的是每个字符的 UTF-8 编码的长度和,而不是直接的字符数量。

    如 len("hello,世界") 的结果是 12 不是 8

     strlen() :与 Go 的  len() 类似,得到的是字符串所占的字节数

     utf8.RuneCountInString() :获取字符串的真正长度,上面的 utf8.RuneCountInString("hello,世界") 的结果是 8。

    注:需import "unicode/utf8"

    获取字符串的真正长度可以使用下面两个函数:
    •  mb_strlen() :需安装 mbstring 扩展
    •  iconv_strlen() :返回字符串的字符数统计,是整型
    字符串拼接
    运算符 + :
    str := "hello, " +
    "world"
    • 字符串之间用加号“+”拼接。如果换行,+ 要放到当前行的末尾,不能放到下一行的开头
    • 使用这种拼接方式,里面的字符串是不可变的,每次运算都会产生一个新的、临时的字符串,给 GC 带来额外的负担,所以性能比较差
    运算符 . :
    $str = "hello, " . "world";
    // 也可以写成:
    $str = "hello, " . "world";
    • 字符串之间用句点 “.”拼接,换行对句点的位置没有要求
    fmt.Sprintf():
    fmt.Sprintf("%d:%s", 2018, "年")
    • 内部使用 []byte 实现,不会产生临时的字符串
    • 内部逻辑复杂,还用到了interface,性能一般
    strings.Join()
    strings.Join([]string{"hello", "world"}, ", ")
    • Join会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入
    • 已有一个数组的情况下,这种拼接方式的效率很高,但如果没有,去构造这个数据的代价也不小。
    bytes.Buffer——优先推荐
    var buffer bytes.Buffer
    buffer.WriteString("hello")
    buffer.WriteString(", ")
    buffer.WriteString("world")
     
    fmt.Print(buffer.String())
    • 使用这种拼接方式,可以把字符串当成可变字符使用,对内存的增长也有优化
    • 如果能预估字符串的长度,还可以用 buffer.Grow() 接口来设置 capacity。
    strings.Builder——推荐
    var b1 strings.Builder
    b1.WriteString("ABC")
    b1.WriteString("DEF")
     
    fmt.Print(b1.String())
    • 内部通过 slice 来保存和管理内容
    • 提供了 Grow() 来支持预定义容量,这样可以避免扩容而创建新的 slice
    • 非线程安全,性能上和 bytes.Buffer 相差无几
    数组
    声明数组
    • 数组元素必须类型唯一,要么都是字符串,要么都是数字类型。如果想让数组元素类型为任意类型,可以使用空接口interface{}作为类型,当使用值时必须先做一个类型判断。
    • 声明时需要确定长度,如果采用不定长数组的方式声明,在初始化时会自动确定好数组的长度。
    ① var arr [2]int //var 数组名称 [数组长度]数组元素类型
    ② var arr = [2]int{1,2} //var 数组名称 = [数组长度]数组元素类型{元素1,元素2,...}
    ③ var arr = [5]string{3: "ab", 4: "cd"} //指定索引位置
    ④ var arr = [...]int{1,2} //var 数组名称 = [...]数组元素类型{元素1,元素2,...},不定长数组声明方式
    ⑤ new():创建的是数组引针,eg.  var arr1 = new([5]int) 
    • 声明时不需要确定长度,且数组元素可以多类型混合
    $arr  = ['a', 'b', 'c', 123];
     
    如果是 Go,会报错:
    # command-line-arguments
    ./arr.go:6:34: cannot use 123 (type int) as type string in array or slice literal
    值传递和
    引用传递
    var arr1 = new([5]int)
    arr := arr1
    arr1[2] = 100
    fmt.Println(arr1[2], arr[2])
     
    var arr2 [5]int
    newarr := arr2
    arr2[2] = 100
    fmt.Println(arr2[2], newarr[2])
    程序输出:
    100 100
    100 0
    new([5]int)创建的是数组指针,arr和arr1指向同一地址,故而修改arr1时arr同样也生效;
    而newarr是由arr2值传递(拷贝),故而修改任何一个都不会改变另一个的值。
    达到与左侧相同的效果,PHP 代码如下:
    $arr1 = [5, 10, 0, 20, 25];
    $arr = &$arr1; //引用传递
    $newArr = $arr1; //值传递
    $arr1[2] = 100;
    echo $arr1[2], $arr[2];
    echo $arr1[2], $newArr[2];
     
    程序输出:
    100 100
    100 0
    PHP中的引用传递使用 & 符号。
    切片
    定义
    • 切片是引用(对底层数组一个连续片段的引用),不需要占用额外的内存,比数组效率高
    • 一个切片未初始化前默认为nil,长度为0
    • 切片的长度可变,可以把切片看成一个长度可变的数组
    PHP中没有切片这个概念,但是在数组函数中有个 array_slice() 函数,可以根据 offset 和 length 返回指定的数组中的一段序列。与 Go 的切片相似。
    $input = array("a", "b", "c", "d", "e");
    $output = array_slice($input, 0, 3);   // returns "a", "b", and "c"
    声明
    ① 切分数组
    var arr = [5]int{1,2,3,4,5} //数组
    var s []type = arr[start:end:max] //切片(包含数组start到end-1之间的元素),end-start表示长度,max-start表示容量
    ② 初始化
    var s = []int{2, 3, 5, 7, 11} //创建了一个长度为 5 的数组并且创建了一个相关切片。
    ③ 切片重组
    var s []type = make([]type, len, cap) //len 是数组的长度也是切片的初始长度,cap是容量,可选参数
    简写为slice := make([]type, len)
    字典
    定义
    • 一种元素对的无序集合,一组称为元素value,另一组为唯一键索引key
    • 未初始化 map 的值为 nil。map 是引用类型
    • map 可以动态增长,声明时不需要定义长度
    PHP的关联数组类似于 Go 的 Map。
    声明
    var mapName map[keyType]valueType
    ② var mapName map[keyType]valueType{k1:v1, k2:v2, ...}
    var mapName = make(map[keyType]valueType, cap) //cap是可选参数,表示容量
    其实 Go 的基本数据类型的知识点以及它和 PHP 的区别绝不止上面列出的这些,对比新旧两种语言的差别意义也不是很大,但对我来说,通过梳理可以达到温故知新的目的。 
  • 相关阅读:
    hdu 5007 水题 (2014西安网赛A题)
    hdu 1698 线段树(成段替换 区间求和)
    poj 3468 线段树 成段增减 区间求和
    hdu 2795 公告板 (单点最值)
    UVaLive 6833 Miscalculation (表达式计算)
    UVaLive 6832 Bit String Reordering (模拟)
    CodeForces 124C Prime Permutation (数论+贪心)
    SPOJ BALNUM (数位DP)
    CodeForces 628D Magic Numbers (数位DP)
    POJ 3252 Round Numbers (数位DP)
  • 原文地址:https://www.cnblogs.com/sunshineliulu/p/11616495.html
Copyright © 2011-2022 走看看