go php 基本数据类型对比

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 字符

字符串定义

  • 双引号(""):双引号中的转义字符会被替换
  • 反引号(``):反引号中原生字符串中的转义字符(如\n)会被原样输出
  • 单引号(''):单引号括起来的单个字符,需要格式化输出,%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 的区别绝不止上面列出的这些,对比新旧两种语言的差别意义也不是很大,但对我来说,通过梳理可以达到温故知新的目的。 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值