mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-26 05:06:42 +08:00
572 lines
28 KiB
HTML
572 lines
28 KiB
HTML
<!DOCTYPE html>
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
<link rel="icon" href="/static/favicon.png">
|
||
<title>02 数据类型:你必须掌握的数据类型有哪些?.md.html</title>
|
||
<!-- Spectre.css framework -->
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
<!-- theme css & js -->
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<div class="book-container">
|
||
<div class="book-sidebar">
|
||
<div class="book-brand">
|
||
<a href="/">
|
||
<img src="/static/favicon.png">
|
||
<span>技术文章摘抄</span>
|
||
</a>
|
||
</div>
|
||
<div class="book-menu uncollapsible">
|
||
<ul class="uncollapsible">
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
</ul>
|
||
|
||
<ul class="uncollapsible">
|
||
<li><a href="../">上一级</a></li>
|
||
</ul>
|
||
|
||
<ul class="uncollapsible">
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/00 开篇词 Go 为开发者的需求设计,带你实现高效工作.md.html">00 开篇词 Go 为开发者的需求设计,带你实现高效工作.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/01 基础入门:编写你的第一个 Go 语言程序.md.html">01 基础入门:编写你的第一个 Go 语言程序.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
<a class="current-tab" href="/专栏/22 讲通关 Go 语言-完/02 数据类型:你必须掌握的数据类型有哪些?.md.html">02 数据类型:你必须掌握的数据类型有哪些?.md.html</a>
|
||
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/03 控制结构:if、for、switch 逻辑语句的那些事儿.md.html">03 控制结构:if、for、switch 逻辑语句的那些事儿.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/04 集合类型:如何正确使用 array、slice 和 map?.md.html">04 集合类型:如何正确使用 array、slice 和 map?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/05 函数和方法:Go 语言中的函数和方法到底有什么不同?.md.html">05 函数和方法:Go 语言中的函数和方法到底有什么不同?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/06 struct 和 interface:结构体与接口都实现了哪些功能?.md.html">06 struct 和 interface:结构体与接口都实现了哪些功能?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/07 错误处理:如何通过 error、deferred、panic 等处理错误?.md.html">07 错误处理:如何通过 error、deferred、panic 等处理错误?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/08 并发基础:Goroutines 和 Channels 的声明与使用.md.html">08 并发基础:Goroutines 和 Channels 的声明与使用.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/09 同步原语:sync 包让你对并发控制得心应手.md.html">09 同步原语:sync 包让你对并发控制得心应手.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/10 Context:你必须掌握的多线程并发控制神器.md.html">10 Context:你必须掌握的多线程并发控制神器.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/11 并发模式:Go 语言中即学即用的高效并发模式.md.html">11 并发模式:Go 语言中即学即用的高效并发模式.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/12 指针详解:在什么情况下应该使用指针?.md.html">12 指针详解:在什么情况下应该使用指针?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/13 参数传递:值、引用及指针之间的区别?.md.html">13 参数传递:值、引用及指针之间的区别?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/14 内存分配:new 还是 make?什么情况下该用谁?.md.html">14 内存分配:new 还是 make?什么情况下该用谁?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/15 运行时反射:字符串和结构体之间如何转换?.md.html">15 运行时反射:字符串和结构体之间如何转换?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/16 非类型安全:让你既爱又恨的 unsafe.md.html">16 非类型安全:让你既爱又恨的 unsafe.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/17 SliceHeader:slice 如何高效处理数据?.md.html">17 SliceHeader:slice 如何高效处理数据?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/18 质量保证:Go 语言如何通过测试保证质量?.md.html">18 质量保证:Go 语言如何通过测试保证质量?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/19 性能优化:Go 语言如何进行代码检查和优化?.md.html">19 性能优化:Go 语言如何进行代码检查和优化?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/20 协作开发:模块化管理为什么能够提升研发效能?.md.html">20 协作开发:模块化管理为什么能够提升研发效能?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/21 网络编程:Go 语言如何玩转 RESTful API 服务?.md.html">21 网络编程:Go 语言如何玩转 RESTful API 服务?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/22 网络编程:Go 语言如何通过 RPC 实现跨平台服务?.md.html">22 网络编程:Go 语言如何通过 RPC 实现跨平台服务?.md.html</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/22 讲通关 Go 语言-完/23 结束语 你的 Go 语言成长之路.md.html">23 结束语 你的 Go 语言成长之路.md.html</a>
|
||
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
<div class="sidebar-toggle-inner"></div>
|
||
</div>
|
||
|
||
<script>
|
||
function add_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.add('show')
|
||
}
|
||
|
||
function remove_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.remove('show')
|
||
}
|
||
|
||
function sidebar_toggle() {
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let content = document.querySelector('.off-canvas-content')
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
sidebar_toggle.classList.remove('extend')
|
||
sidebar.classList.remove('hide')
|
||
content.classList.remove('extend')
|
||
} else { // hide
|
||
sidebar_toggle.classList.add('extend')
|
||
sidebar.classList.add('hide')
|
||
content.classList.add('extend')
|
||
}
|
||
}
|
||
|
||
|
||
function open_sidebar() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.add('show')
|
||
overlay.classList.add('show')
|
||
}
|
||
function hide_canvas() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.remove('show')
|
||
overlay.classList.remove('show')
|
||
}
|
||
|
||
</script>
|
||
|
||
<div class="off-canvas-content">
|
||
<div class="columns">
|
||
<div class="column col-12 col-lg-12">
|
||
<div class="book-navbar">
|
||
<!-- For Responsive Layout -->
|
||
<header class="navbar">
|
||
<section class="navbar-section">
|
||
<a onclick="open_sidebar()">
|
||
<i class="icon icon-menu"></i>
|
||
</a>
|
||
</section>
|
||
</header>
|
||
</div>
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;">
|
||
<div class="book-post">
|
||
<p id="tip" align="center"></p>
|
||
<div><h1>02 数据类型:你必须掌握的数据类型有哪些?</h1>
|
||
<p>上节课的思考题是打印出自己的名字,这个作业比较简单,属于文本的替换,你只需要把我示例中的"Hello 世界"修改成自己的名字即可,比如以我的名字为例,替换为“飞雪无情”。</p>
|
||
<p>经过上一节课的学习,你已经对 Go 语言的程序结构有了初步了解,也准备好了相应的开发环境。但是一个完整的项目需要更复杂的逻辑,不是简单的“Hello 世界”可相比的。这些逻辑通过变量、常量、类型、函数方法、接口、结构体组成,这节课我就将带你认识它们,让你的 Go 语言程序变得更加生动。</p>
|
||
<h3>变量声明</h3>
|
||
<p>变量代表可变的数据类型,也就是说,它在程序执行的过程中可能会被一次甚至多次修改。</p>
|
||
<p>在 Go 语言中,通过 var 声明语句来定义一个变量,定义的时候需要指定这个变量的类型,然后再为它起个名字,并且设置好变量的初始值。所以 var 声明一个变量的格式如下:</p>
|
||
<pre><code>var 变量名 类型 = 表达式
|
||
</code></pre>
|
||
<p>现在我通过一个示例来演示如何定义一个变量,并且设置它的初始值:</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>package main
|
||
|
||
import "fmt"
|
||
|
||
func main() {
|
||
|
||
var i int = 10
|
||
|
||
fmt.Println(i)
|
||
|
||
}
|
||
</code></pre>
|
||
<p>观察上面例子中 main 函数的内容,其中 var i int = 10 就是定义一个类型为 int(整数)、变量名为 i 的变量,它的初始值为 10</p>
|
||
<p>这里为了运行程序,我加了一行 fmt.Println(i),你在上节课中就见到过它,表示打印出变量 i 的值。</p>
|
||
<p>这样做一方面是因为 Go 语言中定义的变量必须使用,否则无法编译通过,这也是 Go 语言比较好的特性,防止定义了变量不使用,导致浪费内存的情况;另一方面,在运行程序的时候可以查看变量 i 的结果。</p>
|
||
<p>通过输入 go run ch02/main.go 命令回车运行,即可看到如下结果:</p>
|
||
<pre><code>$ go run ch02/main.go
|
||
|
||
10
|
||
</code></pre>
|
||
<p>打印的结果是10,和变量的初始值一样。</p>
|
||
<p>因为 Go 语言具有类型推导功能,所以也可以不去刻意地指定变量的类型,而是让 Go 语言自己推导,比如变量 i 也可以用如下的方式声明:</p>
|
||
<pre><code>var i = 10
|
||
</code></pre>
|
||
<p>这样变量 i 的类型默认是 int 类型。</p>
|
||
<p>你也可以一次声明多个变量,把要声明的多个变量放到一个括号中即可,如下面的代码所示:</p>
|
||
<pre><code>var (
|
||
|
||
j int= 0
|
||
|
||
k int= 1
|
||
|
||
)
|
||
</code></pre>
|
||
<p>同理因为类型推导,以上多个变量声明也可以用以下代码的方式书写:</p>
|
||
<pre><code>var (
|
||
|
||
j = 0
|
||
|
||
k = 1
|
||
|
||
)
|
||
</code></pre>
|
||
<p>这样就更简洁了。</p>
|
||
<p>其实不止 int 类型,我后面介绍的 float64、bool、string 等基础类型都可以被自动推导,也就是可以省略定义类型。</p>
|
||
<h3>演示项目目录结构</h3>
|
||
<p>为了让你更好地理解我演示的例子,这里我给出演示项目的目录结构,以后的所有课时都会按照这个目录进行演示。</p>
|
||
<p>我的演示项目结构如下所示:</p>
|
||
<pre><code>gotour
|
||
|
||
├── ch01
|
||
|
||
│ └── main.go
|
||
|
||
├── ch02
|
||
|
||
│ └── main.go
|
||
|
||
└── go.mod
|
||
</code></pre>
|
||
<p>其中 gotour 是演示项目的根目录,所有 Go 语言命令都会在这里执行,比如 go run。</p>
|
||
<p>ch01、ch02 这些目录是按照课时命名的,每一讲都有对应的目录,便于查找相应的源代码。具体的 Go 语言源代码会存放到对应的课时目录中。</p>
|
||
<h3>基础类型</h3>
|
||
<p>任何一门语言都有对应的基础类型,这些基础类型和现实中的事物一一对应,比如整型对应着 1、2、3、100 这些整数,浮点型对应着 1.1、3.4 这些小数等。Go 语言也不例外,它也有自己丰富的基础类型,常用的有:整型、浮点数、布尔型和字符串,下面我就为你详细介绍。</p>
|
||
<h4>整型</h4>
|
||
<p>在 Go 语言中,整型分为:</p>
|
||
<ul>
|
||
<li><strong>有符号整型</strong>:如 int、int8、int16、int32 和 int64。</li>
|
||
<li><strong>无符号整型</strong>:如 uint、uint8、uint16、uint32 和 uint64。</li>
|
||
</ul>
|
||
<p>它们的差别在于,有符号整型表示的数值可以为负数、零和正数,而无符号整型只能为零和正数。</p>
|
||
<p>除了有用“位”(bit)大小表示的整型外,还有 int 和 uint 这两个没有具体 bit 大小的整型,它们的大小可能是 32bit,也可能是 64bit,和硬件设备 CPU 有关。</p>
|
||
<p>在整型中,如果能确定 int 的 bit 就选择比较明确的 int 类型,因为这会让你的程序具备很好的移植性。</p>
|
||
<p>在 Go 语言中,还有一种字节类型 byte,它其实等价于 uint8 类型,可以理解为 uint8 类型的别名,用于定义一个字节,所以字节 byte 类型也属于整型。</p>
|
||
<h4>浮点数</h4>
|
||
<p>浮点数就代表现实中的小数。Go 语言提供了两种精度的浮点数,分别是 float32 和 float64。项目中最常用的是 float64,因为它的精度高,浮点计算的结果相比 float32 误差会更小。</p>
|
||
<p>下面的代码示例定义了两个变量 f32 和 f64,它们的类型分别为 float32 和 float64。</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>var f32 float32 = 2.2
|
||
|
||
var f64 float64 = 10.3456
|
||
|
||
fmt.Println("f32 is",f32,",f64 is",f64)
|
||
</code></pre>
|
||
<p>运行这段程序,会看到如下结果:</p>
|
||
<pre><code>$ go run ch02/main.go
|
||
|
||
f32 is 2.2 ,f64 is 10.3456
|
||
</code></pre>
|
||
<p>**特别注意:**在演示示例的时候,我会尽可能地贴出演示需要的核心代码,也就是说,会省略 package 和 main 函数。如果没有特别说明,它们都是放在main函数中的,可以直接运行。</p>
|
||
<h4>布尔型</h4>
|
||
<p>一个布尔型的值只有两种:true 和 false,它们代表现实中的“是”和“否”。它们的值会经常被用于一些判断中,比如 if 语句(以后的课时会详细介绍)等。Go 语言中的布尔型使用关键字 bool 定义。</p>
|
||
<p>下面的代码声明了两个变量,你可以自己运行,看看打印输出的结果。</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>var bf bool =false
|
||
|
||
var bt bool = true
|
||
|
||
fmt.Println("bf is",bf,",bt is",bt)
|
||
</code></pre>
|
||
<p>布尔值可以用于一元操作符 !,表示逻辑非的意思,也可以用于二元操作符 &&、||,它们分别表示逻辑和、逻辑或。</p>
|
||
<h4>字符串</h4>
|
||
<p>Go 语言中的字符串可以表示为任意的数据,比如以下代码,在 Go 语言中,字符串通过类型 string 声明:</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>var s1 string = "Hello"
|
||
|
||
var s2 string = "世界"
|
||
|
||
fmt.Println("s1 is",s1,",s2 is",s2)
|
||
</code></pre>
|
||
<p>运行程序就可以看到打印的字符串结果。</p>
|
||
<p>在 Go 语言中,可以通过操作符 + 把字符串连接起来,得到一个新的字符串,比如将上面的 s1 和 s2 连接起来,如下所示:</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>fmt.Println("s1+s2=",s1+s2)
|
||
</code></pre>
|
||
<p>由于 s1 表示字符串“Hello”,s2 表示字符串“世界”,在终端输入 go run ch02/main.go 后,就可以打印出它们连接起来的结果“Hello世界”,如以下代码所示:</p>
|
||
<pre><code>s1+s2= Hello世界
|
||
</code></pre>
|
||
<p>字符串也可以通过 += 运算符操作,你自己可以试试 s1+=s2 会得到什么新的字符串。</p>
|
||
<h4>零值</h4>
|
||
<p>零值其实就是一个变量的默认值,在 Go 语言中,如果我们声明了一个变量,但是没有对其进行初始化,那么 Go 语言会自动初始化其值为对应类型的零值。比如数字类的零值是 0,布尔型的零值是 false,字符串的零值是 "" 空字符串等。</p>
|
||
<p>通过下面的代码示例,就可以验证这些基础类型的零值:</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>var zi int
|
||
|
||
var zf float64
|
||
|
||
var zb bool
|
||
|
||
var zs string
|
||
|
||
fmt.Println(zi,zf,zb,zs)
|
||
</code></pre>
|
||
<h3>变量</h3>
|
||
<h4>变量简短声明</h4>
|
||
<p>有没有发现,上面我们演示的示例都有一个 var 关键字,但是这样写代码很烦琐。借助类型推导,Go 语言提供了变量的简短声明 :=,结构如下:</p>
|
||
<pre><code>变量名:=表达式
|
||
</code></pre>
|
||
<p>借助 Go 语言简短声明功能,变量声明就会非常简洁,比如以上示例中的变量,可以通过如下代码简短声明:</p>
|
||
<pre><code>i:=10
|
||
|
||
bf:=false
|
||
|
||
s1:="Hello"
|
||
</code></pre>
|
||
<p>在实际的项目实战中,如果你能为声明的变量初始化,那么就选择简短声明方式,这种方式也是使用最多的。</p>
|
||
<h4>指针</h4>
|
||
<p>在 Go 语言中,指针对应的是变量在内存中的存储位置,也就说指针的值就是变量的内存地址。通过 & 可以获取一个变量的地址,也就是指针。</p>
|
||
<p>在以下的代码中,pi 就是指向变量 i 的指针。要想获得指针 pi 指向的变量值,通过*pi这个表达式即可。尝试运行这段程序,会看到输出结果和变量 i 的值一样。</p>
|
||
<pre><code>pi:=&i
|
||
|
||
fmt.Println(*pi)
|
||
</code></pre>
|
||
<h4>赋值</h4>
|
||
<p>在讲变量的时候,我说过变量是可以修改的,那么怎么修改呢?这就是赋值语句要做的事情。最常用也是最简单的赋值语句就是 =,如下代码所示:</p>
|
||
<pre><code>i = 20
|
||
|
||
fmt.Println("i的新值是",i)
|
||
</code></pre>
|
||
<p>这样变量 i 就被修改了,它的新值是 20。</p>
|
||
<h3>常量</h3>
|
||
<p>一门编程语言,有变量就有常量,Go 语言也不例外。在程序中,常量的值是指在编译期就确定好的,一旦确定好之后就不能被修改,这样就可以防止在运行期被恶意篡改。</p>
|
||
<h4>常量的定义</h4>
|
||
<p>常量的定义和变量类似,只不过它的关键字是 const。</p>
|
||
<p>下面的示例定义了一个常量 name,它的值是“飞雪无情”。因为 Go 语言可以类型推导,所以在常量声明时也可以省略类型。</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>const name = "飞雪无情"
|
||
</code></pre>
|
||
<p>在 Go 语言中,只允许布尔型、字符串、数字类型这些基础类型作为常量。</p>
|
||
<h4>iota</h4>
|
||
<p>iota 是一个常量生成器,它可以用来初始化相似规则的常量,避免重复的初始化。假设我们要定义 one、two、three 和 four 四个常量,对应的值分别是 1、2、3 和 4,如果不使用 iota,则需要按照如下代码的方式定义:</p>
|
||
<pre><code>const(
|
||
|
||
one = 1
|
||
|
||
two = 2
|
||
|
||
three =3
|
||
|
||
four =4
|
||
|
||
)
|
||
</code></pre>
|
||
<p>以上声明都要初始化,会比较烦琐,因为这些常量是有规律的(连续的数字),所以可以使用 iota 进行声明,如下所示:</p>
|
||
<pre><code>const(
|
||
|
||
one = iota+1
|
||
|
||
two
|
||
|
||
three
|
||
|
||
four
|
||
|
||
)
|
||
|
||
fmt.Println(one,two,three,four)
|
||
</code></pre>
|
||
<p>你自己可以运行程序,会发现打印的值和上面初始化的一样,也是 1、2、3、4。</p>
|
||
<p>iota 的初始值是 0,它的能力就是在每一个有常量声明的行后面 +1,下面我来分解上面的常量:</p>
|
||
<ol>
|
||
<li>one=(0)+1,这时候 iota 的值为 0,经过计算后,one 的值为 1。</li>
|
||
<li>two=(0+1)+1,这时候 iota 的值会 +1,变成了 1,经过计算后,two 的值为 2。</li>
|
||
<li>three=(0+1+1)+1,这时候 iota 的值会再 +1,变成了 2,经过计算后,three 的值为 3。</li>
|
||
<li>four=(0+1+1+1)+1,这时候 iota 的值会继续再 +1,变成了 3,经过计算后,four 的值为 4。</li>
|
||
</ol>
|
||
<p>如果你定义更多的常量,就依次类推,其中 () 内的表达式,表示 iota 自身 +1 的过程。</p>
|
||
<h3>字符串</h3>
|
||
<p>字符串是 Go 语言中常用的类型,在前面的基础类型小节中已经有过基本的介绍。这一小结会为你更详细地介绍字符串的使用。</p>
|
||
<h4>字符串和数字互转</h4>
|
||
<p>Go 语言是强类型的语言,也就是说不同类型的变量是无法相互使用和计算的,这也是为了保证Go 程序的健壮性,所以不同类型的变量在进行赋值或者计算前,需要先进行类型转换。涉及类型转换的知识点非常多,这里我先介绍这些基础类型之间的转换,更复杂的会在后面的课时介绍。</p>
|
||
<p>以字符串和数字互转这种最常见的情况为例,如下面的代码所示:</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>i2s:=strconv.Itoa(i)
|
||
|
||
s2i,err:=strconv.Atoi(i2s)
|
||
|
||
fmt.Println(i2s,s2i,err)
|
||
</code></pre>
|
||
<p>通过包 strconv 的 Itoa 函数可以把一个 int 类型转为 string,Atoi 函数则用来把 string 转为 int。</p>
|
||
<p>同理对于浮点数、布尔型,Go 语言提供了 strconv.ParseFloat、strconv.ParseBool、strconv.FormatFloat 和 strconv.FormatBool 进行互转,你可以自己试试。</p>
|
||
<p>对于数字类型之间,可以通过强制转换的方式,如以下代码所示:</p>
|
||
<pre><code>i2f:=float64(i)
|
||
|
||
f2i:=int(f64)
|
||
|
||
fmt.Println(i2f,f2i)
|
||
</code></pre>
|
||
<p>这种使用方式比简单,采用“类型(要转换的变量)”格式即可。采用强制转换的方式转换数字类型,可能会丢失一些精度,比如浮点型转为整型时,小数点部分会全部丢失,你可以自己运行上述示例,验证结果。</p>
|
||
<p>把变量转换为相应的类型后,就可以对相同类型的变量进行各种表达式运算和赋值了。</p>
|
||
<h4>Strings 包</h4>
|
||
<p>讲到基础类型,尤其是字符串,不得不提 Go SDK 为我们提供的一个标准包 strings。它是用于处理字符串的工具包,里面有很多常用的函数,帮助我们对字符串进行操作,比如查找字符串、去除字符串的空格、拆分字符串、判断字符串是否有某个前缀或者后缀等。掌握好它,有利于我们的高效编程。</p>
|
||
<p>以下代码是我写的关于 strings 包的一些例子,你自己可以根据<a href="https://golang.google.cn/pkg/strings/">strings 文档</a>自己写一些示例,多练习熟悉它们。</p>
|
||
<p><em><strong>ch02/main.go</strong></em></p>
|
||
<pre><code>//判断s1的前缀是否是H
|
||
|
||
fmt.Println(strings.HasPrefix(s1,"H"))
|
||
|
||
//在s1中查找字符串o
|
||
|
||
fmt.Println(strings.Index(s1,"o"))
|
||
|
||
//把s1全部转为大写
|
||
|
||
fmt.Println(strings.ToUpper(s1))
|
||
</code></pre>
|
||
<h3>总结</h3>
|
||
<p>本节课我讲解了变量、常量的声明、初始化,以及变量的简短声明,同时介绍了常用的基础类型、数字和字符串的转换以及 strings 工具包的使用,有了这些,你就可以写出功能更强大的程序。</p>
|
||
<p>在基础类型中,还有一个没有介绍的基础类型——复数,它不常用,就留给你来探索。这里给你一个提示:复数是用 complex 这个内置函数创建的。</p>
|
||
<p>本节课的思考题是:如何在一个字符串中查找某个字符串是否存在?提示一下,Go 语言自带的 strings 包里有现成的函数哦。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/22 讲通关 Go 语言-完/01 基础入门:编写你的第一个 Go 语言程序.md.html">上一页</a>
|
||
</div>
|
||
<div style="float: right">
|
||
<a href="/专栏/22 讲通关 Go 语言-完/03 控制结构:if、for、switch 逻辑语句的那些事儿.md.html">下一页</a>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
</div>
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70996dad69d83d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
</body>
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
|
||
function gtag() {
|
||
dataLayer.push(arguments);
|
||
}
|
||
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-NPSEEVD756');
|
||
var path = window.location.pathname
|
||
var cookie = getCookie("lastPath");
|
||
console.log(path)
|
||
if (path.replace("/", "") === "") {
|
||
if (cookie.replace("/", "") !== "") {
|
||
console.log(cookie)
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
}
|
||
} else {
|
||
setCookie("lastPath", path)
|
||
}
|
||
|
||
function setCookie(cname, cvalue) {
|
||
var d = new Date();
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
var expires = "expires=" + d.toGMTString();
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
}
|
||
|
||
function getCookie(cname) {
|
||
var name = cname + "=";
|
||
var ca = document.cookie.split(';');
|
||
for (var i = 0; i < ca.length; i++) {
|
||
var c = ca[i].trim();
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
}
|
||
return "";
|
||
}
|
||
|
||
</script>
|
||
|
||
</html>
|