## 貨幣轉換和float64注意事項
計算貨幣始終是一個棘手的事情。將money表示為float64可能很誘人,但這會導致計算時出現一些令人討厭的舍入錯誤。出于這個原因,最好以美分來計算貨幣并將其存儲為Int64。
從表單,命令行或其他來源收集用戶輸入時,錢通常以美元形式表示。 因此,最好將其視為字符串,并將該字符串直接轉換為便士而不進行浮點轉換。 本節將介紹將貨幣的字符串表示形式轉換為int64(便士)并再次返回的方法(大家在進行微信支付開發的時候可以看到,結算單位為分,傳遞的金額為整數)。
### 實踐
1. 建立dollars.go:
```
package currency
import (
"errors"
"strconv"
"strings"
)
// ConvertStringDollarsToPennies 接收美元字符串并轉換為int64
func ConvertStringDollarsToPennies(amount string) (int64, error) {
// 檢查傳入參數是否合法
_, err := strconv.ParseFloat(amount, 64)
if err != nil {
return 0, err
}
// 以"."進行分割
groups := strings.Split(amount, ".")
// 如果沒有"."則取切片中的第一個元素
result := groups[0]
r := ""
// 處理"."后的數據
if len(groups) == 2 {
if len(groups[1]) != 2 {
return 0, errors.New("invalid cents")
}
r = groups[1]
if len(r) > 2 {
r = r[:2]
}
}
// 填充0
for len(r) < 2 {
r += "0"
}
result += r
// 轉換為int
return strconv.ParseInt(result, 10, 64)
}
```
2. 建立pennies.go:
```
package currency
import (
"strconv"
)
// ConvertPenniesToDollarString 與上面的例子類似 這是將操作方式逆轉
func ConvertPenniesToDollarString(amount int64) string {
result := strconv.FormatInt(amount, 10)
negative := false
if result[0] == '-' {
result = result[1:]
negative = true
}
for len(result) < 3 {
result = "0" + result
}
length := len(result)
result = result[0:length-2] + "." + result[length-2:]
if negative {
result = "-" + result
}
return result
}
```
3. 建立main.go:
```
package main
import (
"fmt"
"github.com/agtorre/go-cookbook/chapter3/currency"
)
func main() {
userInput := "15.93"
pennies, err := currency.ConvertStringDollarsToPennies(userInput)
if err != nil {
panic(err)
}
fmt.Printf("User input converted to %d pennies\n", pennies)
pennies += 15
dollars := currency.ConvertPenniesToDollarString(pennies)
fmt.Printf("Added 15 cents, new values is %s dollars\n", dollars)
}
```
4. 這會輸出:
```
User input converted to 1593 pennies
Added 15 cents, new values is 16.08 dollars
```
### 說明
本節使用strconv和strings包來轉換字符串格式的美元和int64中格式的便士。其中轉換為float64僅作為驗證之用。
strconv.ParseInt和strconv.FormatInt函數對于轉換為int64和字符串非常有用。我們還利用了Go字符串可以根據需要輕松添加和切片的特性。
* * * *
學識淺薄,錯誤在所難免。歡迎在群中就本書提出修改意見,以饗后來者,長風拜謝。
Golang中國(211938256)
beego實戰(258969317)
Go實踐(386056972)
- 前言
- 第一章 I/O和文件系統
- 常見 I/O 接口
- 使用bytes和strings包
- 操作文件夾和文件
- 使用CSV格式化數據
- 操作臨時文件
- 使用 text/template和HTML/templates包
- 第二章 命令行工具
- 解析命令行flag標識
- 解析命令行參數
- 讀取和設置環境變量
- 操作TOML,YAML和JSON配置文件
- 操做Unix系統下的pipe管道
- 處理信號量
- ANSI命令行著色
- 第三章 數據類型轉換和解析
- 數據類型和接口轉換
- 使用math包和math/big包處理數字類型
- 貨幣轉換和float64注意事項
- 使用指針和SQL Null類型進行編碼和解碼
- 對Go數據編碼和解碼
- Go中的結構體標簽和反射
- 通過閉包實現集合操作
- 第四章 錯誤處理
- 錯誤接口
- 使用第三方errors包
- 使用log包記錄錯誤
- 結構化日志記錄
- 使用context包進行日志記錄
- 使用包級全局變量
- 處理恐慌
- 第五章 數據存儲
- 使用database/sql包操作MySQL
- 執行數據庫事務接口
- SQL的連接池速率限制和超時
- 操作Redis
- 操作MongoDB
- 創建存儲接口以實現數據可移植性
- 第六章 Web客戶端和APIs
- 使用http.Client
- 調用REST API
- 并發操作客戶端請求
- 使用OAuth2
- 實現OAuth2令牌存儲接口
- 封裝http請求客戶端
- 理解GRPC的使用
- 第七章 網絡服務
- 處理Web請求
- 使用閉包進行狀態處理
- 請求參數驗證
- 內容渲染
- 使用中間件
- 構建反向代理
- 將GRPC導出為JSON API
- 第八章 測試
- 使用標準庫進行模擬
- 使用Mockgen包
- 使用表驅動測試
- 使用第三方測試工具
- 模糊測試
- 行為驅動測試
- 第九章 并發和并行
- 第十章 分布式系統
- 第十一章 響應式編程和數據流
- 第十二章 無服務器編程
- 第十三章 性能改進