# 基礎資料型別
golang內建基礎型別包括:布林(bool)、數值、字串(string)。
## 布林
Go的布林型別為`bool`,值是 `true` 或`false`,預設為false。
以下三種方式皆可宣告
```go=
var enabled,disabled bool = false,true
var enabled,disabled = false,true
enabled,disabled := false,true
```
賦值
```go=
enabled = true
```
### 布林運算
Go語言內建的運算子有:
- 算術運算子
- 比較運算子
- 邏輯運算子
- 位元運算子
- 賦值運算子
- 其他運算子
可以對布林值使用 **邏輯運算子** 以及相等 `==` 或不等 `!=` 。

布林型別範例:
```go=
truth := 3 <= 5
falsehood := 10 > 12
res1 := 10 > 15 && 4 == 5
res2 := 2*2 == 4 || 10%3 == 0
fmt.Println(truth, falsehood, res1, res2) // true false false true
```
## 數值
分為整數、浮點數、複數。
### 整數
整數型別有 **無符號** 和 **有符號** 兩種,Go同時支援 `int` 和 `unit`,這兩種型別的長度相同,但具體長度取決於不同編譯器的實現。
:::info
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
:::

**另外還有 byte(uint8的別名) 和 rune(int32的別名)**
:::success
Golang 沒有 `char` 資料型別。它使用 `byte` 和 `rune` 來表示字元值。
byte 資料型別用於表示 ASCII 字元,以及 rune 資料型別用於表示以 UTF-8 格式編碼的一組更廣泛的 Unicode 字元。
:::
### 浮點數
用於儲存帶小數部分的數字(如:3.1415926、123.45)。沒有 `float` 型別
:::info
float32 float64
:::
`float32` 在記憶體中佔用 32 位元,並以**單精度**浮點數格式儲存數值。
`float64` 在記憶體中佔用 64 位元,並以**雙精度**浮點數格式儲存數值。
浮點數的預設型別是 `float64`。
### 複數
:::info
complex64 complex128
:::
`complex64`:實部和虛部都是 `float32` 型別。
`complex128`:實部和虛部都是 `float64` 型別。
複數的預設型別是 `complex128`
#### 宣告複數
```go=
x := 3 + 2i //type complex128
fmt.Println(x) // (3+2i)
```
使用變數來建立複數需要使用到內建的 `complex` 函數:(複數的實部和虛部都必須是相同的浮點數型別)
```go=
a := 3.5
b := 6.2
c := complex(a,b)
fmt.Println(c) // (3.5+6.2i)
```
:::warning
不同型別的變數之間不允許互相賦值或操作,不然在編譯時會引起編譯器報錯。
:::
### 數值運算
可使用 **算術運算子、比較運算子、位元運算子、賦值運算子** 來做數值運算。
#### 算術運算子
設 A = 10 , B = 20

#### 比較運算子
設 A = 10 , B = 20

#### 位元運算子
包括 `&` (and), `|` (or), `^` (xor), `<<` (左移n位,就是乘以2的n次方), `>>` (右移n位,就是除以2的n次方)

假設 p 為 20
p << 2 為 p * 2^2^ = 20 * 4 = 80
p >> 2 為 p / 2^2^ = 20 / 4 = 5
#### 賦值運算子

## 字串
Go的字串都是採用UTF-8字符集編碼,字串由一對雙引號`" "`或反引號` `` `括起來定義。
```go=
var emptyStr string = "" //宣告字串變數 初始化為空字串
var hisName string
hisName = "Jason" //賦值
/* 簡短宣告 */
myAge := "21" //雙引號
myAge := `21` //反引號
```
### 宣告多行字串
使用反引號` `` ` 括起的字串為Raw字串,程式碼怎麼寫就怎麼印,包括空格空行,沒有字元轉義。
```go=
str := `Hello
World`
fmt.Println(str)
```
```go=
Hello
World
```
在字串內使用空格
```go=
str2 := `Hello
World`
fmt.Println(str2)
```
```go=
Hello
World
```
### 字串連接
#### 字串與字串連接
使用 `+` 連接字串
```go=
fmt.Println("Hello " + "World")
```
#### 字串型別的變數之間連接
使用 `,` 隔開
```go=
str1 := "Hello"
str2 := "World"
fmt.Println(str1,str2) //Hello World , 字串型別變數連接會自動在兩個變數之間加入空格
```
#### 字串與其他變數型別連接
使用 `,` 隔開字串與變數
```go=
num := 3
fmt.Println("Number:",num) //Number: 3
```
### 字串分割
使用 `strings.Split(字串,"分割的字符")` 來分割字串。
```go=
str := "Hello, World"
str1 := strings.Split(str, ",")
fmt.Println(str1) // [Hello World]
fmt.Println(str1[0]) // Hello
fmt.Println(str1[1]) // World
```
### 字串替換
使用 `strings.Replace(字串,"被替換的字符","替換的字符",-1)` 來替換字串內容。
```go=
str := "梅花梅花幾月開"
//字串替換, -1表示全部替換, 0表示不替換, 1表示替換第一個, 2表示替換第二個
str1 := strings.Replace(str, "梅花", "桃花", -1)
fmt.Println(str1) // 桃花桃花幾月開
```
leetcode有一題easy題可以使用字串替換快速解出
> **1108.Defanging an IP Address**
>
> Given a valid (IPv4) IP address, return a defanged version of that IP address.
> A defanged IP address replaces every period “.” with “[.]”.
>
> **Example 1:**
>
> Input: address = “1.1.1.1”
> Output: “1[.]1[.]1[.]1”
>
> **Example 2:**
>
> Input: address = “255.100.50.0”
> Output: “255[.]100[.]50[.]0”
```go=
func defangIPaddr(address string) string {
ip := strings.Replace(address, ".", "[.]", -1)
return ip
}
```
### 字串擷取
使用 `str[start : end]` 來擷取字串。
```go=
str := "Hello, World"
str1 := str[3 : 8] //[3,8)
fmt.Println(str1) //lo, W
```
**擷取中文字串**
由於中文字不只是由一個byte組成,所以直接擷取中文字串可能會把一個中文字的編碼截成兩半,導致無法正確擷取內容。
```go=
name := "我是王小明"
fmt.Println("name[:4] = ",name[:4]) //name[:4] = 我?
```
先將其轉為`[]rune`,擷取後再轉回string。
```go=
nameRune := []rune(name)
fmt.Println("string(nameRune[:4]) = ",string(nameRune[:4])) //我是王小
```
## 補充
大寫字母開頭 ( 大駝峰 ) 的變數是可匯出的,也就是其它套件可以讀取的,是 **公有變數**;
小寫字母開頭 ( 小駝峰 ) 的就是不可匯出的,是 **私有變數**。
大寫字母開頭 ( 大駝峰 ) 的函式也是一樣,相當於 class 中的帶 public 關鍵詞的 **公有函式**;
小寫字母開頭 ( 小駝峰 ) 的就是有 private 關鍵詞的 **私有函式**。
```go=
// 公有函式,可以被外部package的代碼所使用
func Test() {
//code
}
// 私有函式,package的内部可見
func test2() {
//code
}
```