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 的区别绝不止上面列出的这些,对比新旧两种语言的差别意义也不是很大,但对我来说,通过梳理可以达到温故知新的目的。 
  • 相关阅读:
    C#中char[]与string之间的转换
    Java文件操作之文件追加 Chars
    冒泡排序法的改进 Chars
    选择排序 Chars
    编译原理 Chars
    Apk反编译 Chars
    VC中常用的方法 Chars
    Node.Js入门级《培训》
    新概念系列之《Part2 Lesson 24 It could be worse》
    《CLR via C#》Part2之Chapter5 基元类型、引用类型和值类型(三)
  • 原文地址:https://www.cnblogs.com/sunshineliulu/p/11616495.html
Copyright © 2011-2022 走看看