print()函数
1. Shell 中的 echo
和 printf
在 Shell 中,没有直接的 print()
函数,但可以使用 echo
或 printf
来实现类似功能。
echo
- 用途:输出字符串或变量内容。
- 语法:
echo "Hello, World!"
- 特点:
- 自动在输出末尾添加换行符。
- 支持变量替换。
name="Alice" echo "Hello, $name!"
- 禁用换行符:
echo -n "Hello, World!"
printf
- 用途:格式化输出。
- 语法:
printf "Hello, %s!\n" "World"
- 特点:
- 支持格式化字符串(如
%s
、%d
)。 - 不会自动添加换行符,需要显式使用
\n
。
- 支持格式化字符串(如
2. Python 中的 print()
在 Python 中,print()
是一个内置函数,用于将内容输出到控制台。
基本用法
- 语法:
print("Hello, World!")
- 特点:
- 自动在输出末尾添加换行符。
- 支持多参数,默认用空格分隔。
print("Hello", "World", "!")
格式化输出
- 使用
f-string
(推荐):name = "Alice" print(f"Hello, {name}!")
- 使用
format()
方法:name = "Alice" print("Hello, {}!".format(name))
- 使用
%
格式化:name = "Alice" print("Hello, %s!" % name)
控制换行
- 禁用换行符:
print("Hello, World!", end="")
3. Golang 中的 fmt.Println()
和 fmt.Printf()
在 Golang 中,print()
功能通过 fmt
包实现,主要有 fmt.Println()
和 fmt.Printf()
。
fmt.Println()
- 用途:输出内容并自动添加换行符。
- 语法:
fmt.Println("Hello, World!")
- 特点:
- 支持多参数,默认用空格分隔。
fmt.Println("Hello", "World", "!")
fmt.Printf()
- 用途:格式化输出。
- 语法:
name := "Alice" fmt.Printf("Hello, %s!\n", name)
- 特点:
- 支持格式化字符串(如
%s
、%d
)。 - 不会自动添加换行符,需要显式使用
\n
。
- 支持格式化字符串(如
fmt.Print()
- 用途:输出内容,不添加换行符。
- 语法:
fmt.Print("Hello, World!")
对比总结
特性 | Shell (echo ) |
Python (print() ) |
Golang (fmt.Println() ) |
---|---|---|---|
基本输出 | echo "Hello, World!" |
print("Hello, World!") |
fmt.Println("Hello, World!") |
格式化输出 | printf |
f-string /format() |
fmt.Printf() |
多参数支持 | 支持 | 支持 | 支持 |
自动换行 | echo 自动换行 |
print() 自动换行 |
fmt.Println() 自动换行 |
禁用换行 | echo -n |
print(..., end="") |
fmt.Print() |
示例代码
Shell
echo "Hello, World!"
printf "Hello, %s!\n" "World"
Python
print("Hello, World!")
name = "Alice"
print(f"Hello, {name}!")
Golang
package main
import "fmt"
func main() {fmt.Println("Hello, World!")name := "Alice"fmt.Printf("Hello, %s!\n", name)
}
input()函数
1. Shell 中的 read
在 Shell 中,使用 read
命令获取用户输入。
基本用法
- 语法:
read -p "Enter your name: " name echo "Hello, $name!"
- 特点:
-p
选项用于显示提示信息。- 输入内容存储在变量中(如
name
)。
多输入
- 可以同时读取多个输入:
read -p "Enter your first and last name: " first last echo "Hello, $first $last!"
隐藏输入(如密码)
- 使用
-s
选项隐藏输入内容:read -s -p "Enter your password: " password echo "Password entered."
2. Python 中的 input()
在 Python 中,input()
是一个内置函数,用于从用户获取输入。
基本用法
- 语法:
name = input("Enter your name: ") print(f"Hello, {name}!")
- 特点:
- 输入内容始终作为字符串返回。
- 如果需要其他类型(如整数),需显式转换:
age = int(input("Enter your age: ")) print(f"You are {age} years old.")
多输入
- 使用
split()
方法处理多输入:first, last = input("Enter your first and last name: ").split() print(f"Hello, {first} {last}!")
隐藏输入(如密码)
- 使用
getpass
模块隐藏输入内容:from getpass import getpass password = getpass("Enter your password: ") print("Password entered.")
3. Golang 中的 fmt.Scan()
和 bufio
在 Golang 中,获取用户输入可以通过 fmt.Scan()
或 bufio
包实现。
fmt.Scan()
- 基本用法:
package main import "fmt" func main() {var name stringfmt.Print("Enter your name: ")fmt.Scan(&name)fmt.Printf("Hello, %s!\n", name) }
- 特点:
- 输入内容存储到变量中(如
name
)。 - 支持多输入:
var first, last string fmt.Print("Enter your first and last name: ") fmt.Scan(&first, &last) fmt.Printf("Hello, %s %s!\n", first, last)
- 输入内容存储到变量中(如
bufio
包
- 基本用法:
package main import ("bufio""fmt""os" ) func main() {reader := bufio.NewReader(os.Stdin)fmt.Print("Enter your name: ")name, _ := reader.ReadString('\n')fmt.Printf("Hello, %s!", name) }
- 特点:
- 读取整行输入,包括换行符。
- 需要手动去除换行符:
name = strings.TrimSpace(name)
隐藏输入(如密码)
- 使用
terminal
包隐藏输入内容:package main import ("fmt""golang.org/x/term""syscall" ) func main() {fmt.Print("Enter your password: ")password, _ := term.ReadPassword(int(syscall.Stdin))fmt.Println("\nPassword entered.") }
对比总结
特性 | Shell (read ) |
Python (input() ) |
Golang (fmt.Scan() ) |
---|---|---|---|
基本用法 | read -p |
input() |
fmt.Scan() |
多输入支持 | 支持 | 支持(需 split() ) |
支持 |
输入类型 | 字符串 | 字符串(需显式转换) | 支持多种类型 |
隐藏输入 | read -s |
getpass.getpass() |
term.ReadPassword() |
读取整行 | 默认行为 | 默认行为 | bufio.NewReader() |
示例代码
Shell
read -p "Enter your name: " name
echo "Hello, $name!"
Python
name = input("Enter your name: ")
print(f"Hello, {name}!")
Golang
package main
import "fmt"
func main() {var name stringfmt.Print("Enter your name: ")fmt.Scan(&name)fmt.Printf("Hello, %s!\n", name)
}
代码缩进
1. Shell 中的缩进
在 Shell 脚本中,缩进主要是为了提高代码的可读性,不会影响代码的执行逻辑。
基本规范
- 推荐使用 2 或 4 个空格作为缩进单位。
- 避免使用 Tab 键,因为不同环境下 Tab 的显示可能不一致。
- 条件语句和循环语句通常需要缩进:
if [ "$name" == "Alice" ]; thenecho "Hello, Alice!" elseecho "Hello, stranger!" fi
- 函数定义也需要缩进:
greet() {echo "Hello, World!" }
示例
#!/bin/bash
# 缩进示例
for i in {1..5}; doif [ $i -eq 3 ]; thenecho "Found 3!"elseecho "Number: $i"fi
done
2. Python 中的缩进
在 Python 中,缩进是语法的一部分,直接影响代码的执行逻辑。
基本规范
- 强制使用缩进来表示代码块。
- 推荐使用 4 个空格作为缩进单位。
- 避免混合使用空格和 Tab,建议在编辑器中设置 Tab 为 4 个空格。
- 条件语句、循环语句、函数定义和类定义都需要缩进:
if name == "Alice":print("Hello, Alice!") else:print("Hello, stranger!")
示例
# 缩进示例
def greet(name):if name == "Alice":print("Hello, Alice!")else:print("Hello, stranger!")
for i in range(1, 6):if i == 3:print("Found 3!")else:print(f"Number: {i}")
3. Golang 中的缩进
在 Golang 中,缩进主要是为了提高代码的可读性,不会影响代码的执行逻辑。
基本规范
- 推荐使用 Tab 键作为缩进单位,这是 Golang 的官方规范。
- 代码块(如函数、条件语句、循环语句)需要缩进:
if name == "Alice" {fmt.Println("Hello, Alice!") } else {fmt.Println("Hello, stranger!") }
- 函数定义也需要缩进:
func greet(name string) {fmt.Printf("Hello, %s!\n", name) }
示例
package main
import "fmt"
// 缩进示例
func main() {name := "Alice"if name == "Alice" {fmt.Println("Hello, Alice!")} else {fmt.Println("Hello, stranger!")}for i := 1; i <= 5; i++ {if i == 3 {fmt.Println("Found 3!")} else {fmt.Printf("Number: %d\n", i)}}
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
缩进是否强制 | 否 | 是 | 否 |
推荐缩进单位 | 2 或 4 个空格 | 4 个空格 | Tab |
代码块是否缩进 | 是 | 是 | 是 |
混合空格和 Tab | 不推荐 | 禁止 | 不推荐 |
示例 | if [ ]; then + 缩进 |
if: + 缩进 |
if { + 缩进 |
代码编写规范
1. Shell 脚本编写规范
命名规范
- 变量名:使用大写字母和下划线,如
MY_VARIABLE
。 - 函数名:使用小写字母和下划线,如
my_function
。 - 脚本名:使用小写字母和下划线,如
my_script.sh
。
注释
- 单行注释:使用
#
。# 这是一个单行注释
- 多行注释:使用
:<<'EOF'
或连续的单行注释。
:<<'EOF'这是一个多行注释EOF
代码结构
- Shebang:在脚本开头指定解释器,如
#!/bin/bash
。 - 变量定义:在脚本开头定义变量。
- 函数定义:在脚本中部定义函数。
- 主逻辑:在脚本尾部编写主逻辑。
示例
#!/bin/bash
# 脚本名称: my_script.sh
# 描述: 这是一个示例脚本
# 变量定义
MY_VARIABLE="Hello, World!"
# 函数定义
my_function() {echo "$MY_VARIABLE"
}
# 主逻辑
my_function
2. Python 编写规范
命名规范
- 变量名:使用小写字母和下划线,如
my_variable
。 - 函数名:使用小写字母和下划线,如
my_function
。 - 类名:使用驼峰命名法,如
MyClass
。 - 模块名:使用小写字母和下划线,如
my_module.py
。
注释
- 单行注释:使用
#
。# 这是一个单行注释
- 多行注释:使用三引号
"""
或'''
。""" 这是一个 多行注释 """
代码结构
- 导入模块:在脚本开头导入模块。
- 常量定义:在模块级别定义常量。
- 函数定义:在模块级别定义函数。
- 类定义:在模块级别定义类。
- 主逻辑:使用
if __name__ == "__main__":
包裹主逻辑。
示例
# 模块名称: my_module.py
# 描述: 这是一个示例模块
# 导入模块
import sys
# 常量定义
MY_CONSTANT = "Hello, World!"
# 函数定义
def my_function():print(MY_CONSTANT)
# 类定义
class MyClass:def __init__(self):self.message = MY_CONSTANTdef print_message(self):print(self.message)
# 主逻辑
if __name__ == "__main__":my_function()obj = MyClass()obj.print_message()
3. Golang 编写规范
命名规范
- 变量名:使用驼峰命名法,如
myVariable
。 - 函数名:使用驼峰命名法,如
myFunction
。 - 类型名:使用驼峰命名法,如
MyType
。 - 包名:使用小写字母,如
mypackage
。
注释
- 单行注释:使用
//
。// 这是一个单行注释
- 多行注释:使用
/* */
。/* 这是一个 多行注释 */
代码结构
- 包声明:在文件开头声明包名,如
package main
。 - 导入包:在包声明后导入包。
- 常量定义:在包级别定义常量。
- 变量定义:在包级别定义变量。
- 函数定义:在包级别定义函数。
- 类型定义:在包级别定义类型。
- 主逻辑:在
main
函数中编写主逻辑。
示例
// 包名称: main
// 描述: 这是一个示例程序
// 导入包
import "fmt"
// 常量定义
const myConstant = "Hello, World!"
// 变量定义
var myVariable = myConstant
// 函数定义
func myFunction() {fmt.Println(myVariable)
}
// 类型定义
type MyType struct {message string
}
// 方法定义
func (t *MyType) printMessage() {fmt.Println(t.message)
}
// 主逻辑
func main() {myFunction()obj := MyType{message: myConstant}obj.printMessage()
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
命名规范 | 大写+下划线(变量) | 小写+下划线(变量) | 驼峰命名法 |
注释 | # 和 :<<'EOF' |
# 和 """ |
// 和 /* */ |
代码结构 | Shebang + 变量 + 函数 | 导入 + 常量 + 函数 + 类 | 包声明 + 导入 + 常量 + 函数 + 类型 |
主逻辑 | 直接编写 | if __name__ == "__main__": |
main 函数 |
保留字和标识符
1. 保留字(Keywords)
保留字是编程语言中具有特殊含义的单词,不能用作标识符(如变量名、函数名等)。
Shell 中的保留字
Shell 中的保留字包括:
- 控制结构:
if
,then
,else
,elif
,fi
,case
,esac
,for
,while
,until
,do
,done
- 函数定义:
function
- 其他:
break
,continue
,return
,local
,readonly
,export
Python 中的保留字
Python 中的保留字包括:
- 控制结构:
if
,else
,elif
,for
,while
,break
,continue
,pass
,return
- 函数定义:
def
,lambda
- 类定义:
class
- 异常处理:
try
,except
,finally
,raise
- 其他:
import
,from
,as
,with
,global
,nonlocal
,assert
,del
,yield
Golang 中的保留字
Golang 中的保留字包括:
- 控制结构:
if
,else
,for
,switch
,case
,default
,break
,continue
,return
- 函数定义:
func
- 类型定义:
type
,struct
,interface
- 其他:
var
,const
,package
,import
,go
,chan
,defer
,fallthrough
,goto
,map
,range
,select
2. 标识符(Identifiers)
标识符是用户定义的名称,用于变量、函数、类、模块等。标识符的命名需要遵循一定的规则。
Shell 中的标识符
- 规则:
- 由字母、数字和下划线组成。
- 不能以数字开头。
- 区分大小写。
- 示例:
my_var="Hello" MY_VAR="World"
Python 中的标识符
- 规则:
- 由字母、数字和下划线组成。
- 不能以数字开头。
- 区分大小写。
- 不能使用保留字。
- 示例:
my_var = "Hello" MyVar = "World"
Golang 中的标识符
- 规则:
- 由字母、数字和下划线组成。
- 不能以数字开头。
- 区分大小写。
- 不能使用保留字。
- 示例:
myVar := "Hello" MyVar := "World"
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
保留字 | if , then , for 等 |
if , else , def 等 |
if , else , func 等 |
标识符规则 | 字母、数字、下划线 | 字母、数字、下划线 | 字母、数字、下划线 |
是否区分大小写 | 是 | 是 | 是 |
是否以数字开头 | 否 | 否 | 否 |
是否使用保留字 | 否 | 否 | 否 |
最佳实践
- 命名规范:
- 使用有意义的名称,避免使用单字母或缩写。
- 遵循语言的命名约定(如 Python 使用小写+下划线,Golang 使用驼峰命名法)。
- 避免冲突:
- 不要使用保留字作为标识符。
- 避免使用与内置函数或模块同名的标识符。
- 一致性:
- 在整个项目中保持命名风格一致。
示例
Shell
# 保留字
if [ "$name" == "Alice" ]; thenecho "Hello, Alice!"
fi
# 标识符
my_var="Hello"
echo $my_var
Python
# 保留字
if name == "Alice":print("Hello, Alice!")
# 标识符
my_var = "Hello"
print(my_var)
Golang
package main
import "fmt"
// 保留字
func main() {if name == "Alice" {fmt.Println("Hello, Alice!")}
}
// 标识符
var myVar = "Hello"
fmt.Println(myVar)
变量定义与使用
1. Shell 中的变量
定义变量
- 语法:
my_var="Hello, World!"
- 特点:
- 变量名由字母、数字和下划线组成,不能以数字开头。
- 等号
=
两边不能有空格。 - 变量值可以是字符串、数字或命令输出。
使用变量
- 引用变量:使用
$
符号。echo $my_var
- 双引号 vs 单引号:
- 双引号允许变量替换,单引号不允许。
echo "$my_var" # 输出: Hello, World! echo '$my_var' # 输出: $my_var
- 命令输出赋值:
current_date=$(date) echo "Today is $current_date"
示例
#!/bin/bash
# 定义变量
greeting="Hello, World!"
# 使用变量
echo $greeting
# 命令输出赋值
current_date=$(date)
echo "Today is $current_date"
2. Python 中的变量
定义变量
- 语法:
my_var = "Hello, World!"
- 特点:
- 变量名由字母、数字和下划线组成,不能以数字开头。
- 变量类型是动态的,无需显式声明。
- 变量值可以是字符串、数字、列表、字典等。
使用变量
- 引用变量:直接使用变量名。
print(my_var)
- 变量类型:可以使用
type()
函数查看。print(type(my_var)) # 输出: <class 'str'>
- 多重赋值:
a, b, c = 1, 2, 3 print(a, b, c) # 输出: 1 2 3
示例
# 定义变量
greeting = "Hello, World!"
# 使用变量
print(greeting)
# 多重赋值
x, y, z = 1, 2, 3
print(x, y, z)
3. Golang 中的变量
定义变量
- 语法:
var myVar string = "Hello, World!"
- 特点:
- 变量名由字母、数字和下划线组成,不能以数字开头。
- 变量类型是静态的,需要显式声明。
- 可以使用
:=
进行简短声明(仅限函数内部)。
myVar := "Hello, World!"
使用变量
- 引用变量:直接使用变量名。
fmt.Println(myVar)
- 变量类型:可以使用
%T
格式化查看。fmt.Printf("Type: %T\n", myVar) // 输出: Type: string
- 多重赋值:
a, b, c := 1, 2, 3 fmt.Println(a, b, c) // 输出: 1 2 3
示例
package main
import "fmt"
func main() {// 定义变量var greeting string = "Hello, World!"// 使用变量fmt.Println(greeting)// 简短声明x, y, z := 1, 2, 3fmt.Println(x, y, z)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
定义语法 | my_var="value" |
my_var = "value" |
var myVar string = "value" |
变量类型 | 动态 | 动态 | 静态 |
简短声明 | 不支持 | 不支持 | myVar := "value" |
多重赋值 | 不支持 | 支持 | 支持 |
引用变量 | $my_var |
my_var |
myVar |
类型检查 | 无 | type() |
%T 格式化 |
最佳实践
- 命名规范:
- 使用有意义的名称,避免使用单字母或缩写。
- 遵循语言的命名约定(如 Python 使用小写+下划线,Golang 使用驼峰命名法)。
- 作用域:
- 在 Shell 中,使用
local
定义局部变量。 - 在 Python 和 Golang 中,变量作用域由代码块决定。
- 在 Shell 中,使用
- 类型安全:
- 在 Golang 中,确保变量类型与赋值一致。
- 在 Python 中,注意动态类型可能带来的问题。
示例
Shell
#!/bin/bash
# 定义变量
greeting="Hello, World!"
# 使用变量
echo $greeting
Python
# 定义变量
greeting = "Hello, World!"
# 使用变量
print(greeting)
Golang
package main
import "fmt"
func main() {// 定义变量var greeting string = "Hello, World!"// 使用变量fmt.Println(greeting)
}
数字类型
1. Shell 中的数字类型
在 Shell 中,数字通常以字符串形式存储,但可以通过命令或运算符进行数值计算。
整数
- 定义:直接赋值。
num=10
- 运算:使用
$(( ))
或expr
。sum=$((num + 5))
浮点数
- 定义:直接赋值。
pi=3.14
- 运算:使用
bc
命令。result=$(echo "scale=2; $pi * 2" | bc)
示例
#!/bin/bash
# 整数
num1=10
num2=5
sum=$((num1 + num2))
echo "Sum: $sum"
# 浮点数
pi=3.14
result=$(echo "scale=2; $pi * 2" | bc)
echo "Result: $result"
2. Python 中的数字类型
在 Python 中,数字类型包括整数、浮点数和复数。
整数
- 定义:直接赋值。
num = 10
- 运算:支持加减乘除等操作。
sum = num + 5
浮点数
- 定义:直接赋值。
pi = 3.14
- 运算:支持加减乘除等操作。
result = pi * 2
复数
- 定义:使用
j
表示虚部。complex_num = 3 + 4j
- 运算:支持加减乘除等操作。
result = complex_num * 2
示例
# 整数
num1 = 10
num2 = 5
sum = num1 + num2
print(f"Sum: {sum}")
# 浮点数
pi = 3.14
result = pi * 2
print(f"Result: {result}")
# 复数
complex_num = 3 + 4j
result = complex_num * 2
print(f"Complex Result: {result}")
3. Golang 中的数字类型
在 Golang 中,数字类型包括整数、浮点数和复数。
整数
- 定义:使用
int
、int8
、int16
、int32
、int64
等类型。var num int = 10
- 运算:支持加减乘除等操作。
sum := num + 5
浮点数
- 定义:使用
float32
、float64
类型。var pi float64 = 3.14
- 运算:支持加减乘除等操作。
result := pi * 2
复数
- 定义:使用
complex64
、complex128
类型。var complexNum complex128 = 3 + 4i
- 运算:支持加减乘除等操作。
result := complexNum * 2
示例
package main
import "fmt"
func main() {// 整数var num1 int = 10var num2 int = 5sum := num1 + num2fmt.Printf("Sum: %d\n", sum)// 浮点数var pi float64 = 3.14result := pi * 2fmt.Printf("Result: %.2f\n", result)// 复数var complexNum complex128 = 3 + 4iresultComplex := complexNum * 2fmt.Printf("Complex Result: %v\n", resultComplex)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
整数类型 | 字符串形式 | int |
int , int8 , int16 等 |
浮点数类型 | 字符串形式 | float |
float32 , float64 |
复数类型 | 不支持 | complex |
complex64 , complex128 |
运算支持 | 需要命令或运算符 | 内置支持 | 内置支持 |
类型安全 | 无 | 动态类型 | 静态类型 |
最佳实践
- 类型选择:
- 在 Golang 中,根据需求选择合适的整数或浮点数类型。
- 在 Python 中,注意浮点数的精度问题。
- 运算效率:
- 在 Golang 中,使用
int
和float64
作为默认类型。 - 在 Python 中,避免频繁的类型转换。
- 在 Golang 中,使用
- 类型检查:
- 在 Golang 中,确保变量类型与赋值一致。
- 在 Python 中,使用
type()
函数检查变量类型。
示例
Shell
#!/bin/bash
# 整数
num1=10
num2=5
sum=$((num1 + num2))
echo "Sum: $sum"
# 浮点数
pi=3.14
result=$(echo "scale=2; $pi * 2" | bc)
echo "Result: $result"
Python
# 整数
num1 = 10
num2 = 5
sum = num1 + num2
print(f"Sum: {sum}")
# 浮点数
pi = 3.14
result = pi * 2
print(f"Result: {result}")
# 复数
complex_num = 3 + 4j
result = complex_num * 2
print(f"Complex Result: {result}")
Golang
package main
import "fmt"
func main() {// 整数var num1 int = 10var num2 int = 5sum := num1 + num2fmt.Printf("Sum: %d\n", sum)// 浮点数var pi float64 = 3.14result := pi * 2fmt.Printf("Result: %.2f\n", result)// 复数var complexNum complex128 = 3 + 4iresultComplex := complexNum * 2fmt.Printf("Complex Result: %v\n", resultComplex)
}
字符串类型
1. Shell 中的字符串
在 Shell 中,字符串是常见的数据类型,通常用引号包裹。
定义字符串
- 单引号:原样输出,不支持变量替换。
str='Hello, World!'
- 双引号:支持变量替换。
name="Alice" str="Hello, $name!"
字符串操作
- 拼接:直接连接。
str1="Hello, " str2="World!" result="$str1$str2"
- 长度:使用
${#str}
。length=${#str}
- 子字符串:使用
${str:start:length}
。substr=${str:0:5}
示例
#!/bin/bash
# 定义字符串
name="Alice"
str="Hello, $name!"
# 字符串操作
length=${#str}
substr=${str:0:5}
# 输出
echo "String: $str"
echo "Length: $length"
echo "Substring: $substr"
2. Python 中的字符串
在 Python 中,字符串是不可变的序列类型。
定义字符串
- 单引号:
str1 = 'Hello, World!'
- 双引号:
str2 = "Hello, World!"
- 三引号:多行字符串。
str3 = """Hello, World!"""
字符串操作
- 拼接:使用
+
或join()
。result = str1 + " " + str2
- 长度:使用
len()
。length = len(str1)
- 子字符串:使用切片。
substr = str1[0:5]
- 格式化:使用
f-string
、format()
或%
。name = "Alice" str4 = f"Hello, {name}!"
示例
# 定义字符串
str1 = 'Hello, World!'
str2 = "Hello, World!"
str3 = """Hello,
World!"""
# 字符串操作
result = str1 + " " + str2
length = len(str1)
substr = str1[0:5]
name = "Alice"
str4 = f"Hello, {name}!"
# 输出
print("String 1:", str1)
print("String 2:", str2)
print("String 3:", str3)
print("Concatenated:", result)
print("Length:", length)
print("Substring:", substr)
print("Formatted:", str4)
3. Golang 中的字符串
在 Golang 中,字符串是只读的字节切片。
定义字符串
- 双引号:
str1 := "Hello, World!"
- 反引号:原样输出,支持多行。
str2 := `Hello, World!`
字符串操作
- 拼接:使用
+
或fmt.Sprintf()
。result := str1 + " " + str2
- 长度:使用
len()
。length := len(str1)
- 子字符串:使用切片。
substr := str1[0:5]
- 格式化:使用
fmt.Sprintf()
。name := "Alice" str3 := fmt.Sprintf("Hello, %s!", name)
示例
package main
import "fmt"
func main() {// 定义字符串str1 := "Hello, World!"str2 := `Hello,World!`// 字符串操作result := str1 + " " + str2length := len(str1)substr := str1[0:5]name := "Alice"str3 := fmt.Sprintf("Hello, %s!", name)// 输出fmt.Println("String 1:", str1)fmt.Println("String 2:", str2)fmt.Println("Concatenated:", result)fmt.Println("Length:", length)fmt.Println("Substring:", substr)fmt.Println("Formatted:", str3)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
定义方式 | 单引号、双引号 | 单引号、双引号、三引号 | 双引号、反引号 |
变量替换 | 双引号支持 | f-string 、format() |
fmt.Sprintf() |
拼接 | 直接连接 | + 或 join() |
+ 或 fmt.Sprintf() |
长度 | ${#str} |
len() |
len() |
子字符串 | ${str:start:length} |
切片 | 切片 |
多行字符串 | 不支持 | 三引号 | 反引号 |
最佳实践
- 格式化字符串:
- 在 Python 中使用
f-string
,在 Golang 中使用fmt.Sprintf()
。
- 在 Python 中使用
- 字符串拼接:
- 在 Python 中,使用
join()
拼接大量字符串以提高性能。 - 在 Golang 中,使用
strings.Builder
拼接大量字符串。
- 在 Python 中,使用
- 字符编码:
- 在 Python 和 Golang 中,注意字符串的编码问题(如 UTF-8)。
示例
Shell
#!/bin/bash
# 定义字符串
name="Alice"
str="Hello, $name!"
# 字符串操作
length=${#str}
substr=${str:0:5}
# 输出
echo "String: $str"
echo "Length: $length"
echo "Substring: $substr"
Python
# 定义字符串
str1 = 'Hello, World!'
str2 = "Hello, World!"
str3 = """Hello,
World!"""
# 字符串操作
result = str1 + " " + str2
length = len(str1)
substr = str1[0:5]
name = "Alice"
str4 = f"Hello, {name}!"
# 输出
print("String 1:", str1)
print("String 2:", str2)
print("String 3:", str3)
print("Concatenated:", result)
print("Length:", length)
print("Substring:", substr)
print("Formatted:", str4)
Golang
package main
import "fmt"
func main() {// 定义字符串str1 := "Hello, World!"str2 := `Hello,World!`// 字符串操作result := str1 + " " + str2length := len(str1)substr := str1[0:5]name := "Alice"str3 := fmt.Sprintf("Hello, %s!", name)// 输出fmt.Println("String 1:", str1)fmt.Println("String 2:", str2)fmt.Println("Concatenated:", result)fmt.Println("Length:", length)fmt.Println("Substring:", substr)fmt.Println("Formatted:", str3)
}
算术运算符
1. Shell 中的算术运算符
在 Shell 中,算术运算通常使用 $(( ))
或 expr
命令。
基本运算符
- 加法:
+
result=$((num1 + num2))
- 减法:
-
result=$((num1 - num2))
- 乘法:
*
result=$((num1 * num2))
- 除法:
/
result=$((num1 / num2))
- 取余:
%
result=$((num1 % num2))
示例
#!/bin/bash
# 定义变量
num1=10
num2=3
# 算术运算
sum=$((num1 + num2))
diff=$((num1 - num2))
prod=$((num1 * num2))
quot=$((num1 / num2))
mod=$((num1 % num2))
# 输出
echo "Sum: $sum"
echo "Difference: $diff"
echo "Product: $prod"
echo "Quotient: $quot"
echo "Modulus: $mod"
2. Python 中的算术运算符
在 Python 中,算术运算符直接支持整数和浮点数运算。
基本运算符
- 加法:
+
result = num1 + num2
- 减法:
-
result = num1 - num2
- 乘法:
*
result = num1 * num2
- 除法:
/
result = num1 / num2
- 取余:
%
result = num1 % num2
- 幂运算:
**
result = num1 ** num2
示例
# 定义变量
num1 = 10
num2 = 3
# 算术运算
sum = num1 + num2
diff = num1 - num2
prod = num1 * num2
quot = num1 / num2
mod = num1 % num2
power = num1 ** num2
# 输出
print(f"Sum: {sum}")
print(f"Difference: {diff}")
print(f"Product: {prod}")
print(f"Quotient: {quot}")
print(f"Modulus: {mod}")
print(f"Power: {power}")
3. Golang 中的算术运算符
在 Golang 中,算术运算符支持整数和浮点数运算。
基本运算符
- 加法:
+
result := num1 + num2
- 减法:
-
result := num1 - num2
- 乘法:
*
result := num1 * num2
- 除法:
/
result := num1 / num2
- 取余:
%
result := num1 % num2
示例
package main
import "fmt"
func main() {// 定义变量num1 := 10num2 := 3// 算术运算sum := num1 + num2diff := num1 - num2prod := num1 * num2quot := num1 / num2mod := num1 % num2// 输出fmt.Printf("Sum: %d\n", sum)fmt.Printf("Difference: %d\n", diff)fmt.Printf("Product: %d\n", prod)fmt.Printf("Quotient: %d\n", quot)fmt.Printf("Modulus: %d\n", mod)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
加法 | + |
+ |
+ |
减法 | - |
- |
- |
乘法 | * |
* |
* |
除法 | / |
/ |
/ |
取余 | % |
% |
% |
幂运算 | 不支持 | ** |
不支持 |
浮点数运算 | 使用 bc 命令 |
直接支持 | 直接支持 |
表达式语法 | $(( )) 或 expr |
直接支持 | 直接支持 |
最佳实践
- 类型安全:
- 在 Golang 中,确保运算操作数的类型一致。
- 在 Python 中,注意整数除法和浮点数除法的区别。
- 性能优化:
- 在 Shell 中,使用
$(( ))
替代expr
以提高性能。 - 在 Python 中,使用
math
模块进行复杂数学运算。
- 在 Shell 中,使用
- 错误处理:
- 在 Shell 中,检查除零错误。
- 在 Golang 中,处理可能的溢出或除零错误。
示例
Shell
#!/bin/bash
# 定义变量
num1=10
num2=3
# 算术运算
sum=$((num1 + num2))
diff=$((num1 - num2))
prod=$((num1 * num2))
quot=$((num1 / num2))
mod=$((num1 % num2))
# 输出
echo "Sum: $sum"
echo "Difference: $diff"
echo "Product: $prod"
echo "Quotient: $quot"
echo "Modulus: $mod"
Python
# 定义变量
num1 = 10
num2 = 3
# 算术运算
sum = num1 + num2
diff = num1 - num2
prod = num1 * num2
quot = num1 / num2
mod = num1 % num2
power = num1 ** num2
# 输出
print(f"Sum: {sum}")
print(f"Difference: {diff}")
print(f"Product: {prod}")
print(f"Quotient: {quot}")
print(f"Modulus: {mod}")
print(f"Power: {power}")
Golang
package main
import "fmt"
func main() {// 定义变量num1 := 10num2 := 3// 算术运算sum := num1 + num2diff := num1 - num2prod := num1 * num2quot := num1 / num2mod := num1 % num2// 输出fmt.Printf("Sum: %d\n", sum)fmt.Printf("Difference: %d\n", diff)fmt.Printf("Product: %d\n", prod)fmt.Printf("Quotient: %d\n", quot)fmt.Printf("Modulus: %d\n", mod)
}
索引
1. Shell 中的索引
在 Shell 中,索引主要用于访问字符串或数组中的元素。
字符串索引
- 语法:使用
${str:start:length}
。str="Hello, World!" substr=${str:0:5} # 获取前5个字符
数组索引
- 语法:使用
${array[index]}
。array=("Alice" "Bob" "Charlie") echo ${array[1]} # 输出: Bob
示例
#!/bin/bash
# 字符串索引
str="Hello, World!"
substr=${str:0:5}
echo "Substring: $substr"
# 数组索引
array=("Alice" "Bob" "Charlie")
echo "Second element: ${array[1]}"
2. Python 中的索引
在 Python 中,索引用于访问字符串、列表、元组等序列类型中的元素。
字符串索引
- 语法:使用
str[index]
。str = "Hello, World!" char = str[0] # 获取第一个字符
- 切片:使用
str[start:end]
。substr = str[0:5] # 获取前5个字符
列表索引
- 语法:使用
list[index]
。list = ["Alice", "Bob", "Charlie"] element = list[1] # 获取第二个元素
示例
# 字符串索引
str = "Hello, World!"
char = str[0]
substr = str[0:5]
print("First character:", char)
print("Substring:", substr)
# 列表索引
list = ["Alice", "Bob", "Charlie"]
element = list[1]
print("Second element:", element)
3. Golang 中的索引
在 Golang 中,索引用于访问字符串、数组、切片等类型中的元素。
字符串索引
- 语法:使用
str[index]
。str := "Hello, World!" char := str[0] // 获取第一个字符
- 切片:使用
str[start:end]
。substr := str[0:5] // 获取前5个字符
数组/切片索引
- 语法:使用
array[index]
。array := [3]string{"Alice", "Bob", "Charlie"} element := array[1] // 获取第二个元素
示例
package main
import "fmt"
func main() {// 字符串索引str := "Hello, World!"char := str[0]substr := str[0:5]fmt.Printf("First character: %c\n", char)fmt.Println("Substring:", substr)// 数组索引array := [3]string{"Alice", "Bob", "Charlie"}element := array[1]fmt.Println("Second element:", element)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
字符串索引 | ${str:start:length} |
str[index] |
str[index] |
字符串切片 | ${str:start:length} |
str[start:end] |
str[start:end] |
数组/列表索引 | ${array[index]} |
list[index] |
array[index] |
索引从 0 开始 | 是 | 是 | 是 |
支持负索引 | 否 | 是 | 否 |
类型安全 | 无 | 动态类型 | 静态类型 |
最佳实践
- 边界检查:
- 在 Golang 中,确保索引在有效范围内,否则会引发运行时错误。
- 在 Python 中,使用负索引时注意其含义(从末尾开始计数)。
- 切片操作:
- 在 Python 和 Golang 中,切片操作返回一个新的序列,不会修改原序列。
- 性能优化:
- 在 Golang 中,使用切片代替数组以提高灵活性。
- 在 Python 中,使用列表推导式或生成器表达式处理大量数据。
示例
Shell
#!/bin/bash
# 字符串索引
str="Hello, World!"
substr=${str:0:5}
echo "Substring: $substr"
# 数组索引
array=("Alice" "Bob" "Charlie")
echo "Second element: ${array[1]}"
Python
# 字符串索引
str = "Hello, World!"
char = str[0]
substr = str[0:5]
print("First character:", char)
print("Substring:", substr)
# 列表索引
list = ["Alice", "Bob", "Charlie"]
element = list[1]
print("Second element:", element)
Golang
package main
import "fmt"
func main() {// 字符串索引str := "Hello, World!"char := str[0]substr := str[0:5]fmt.Printf("First character: %c\n", char)fmt.Println("Substring:", substr)// 数组索引array := [3]string{"Alice", "Bob", "Charlie"}element := array[1]fmt.Println("Second element:", element)
}
切片
1. Shell 中的切片
在 Shell 中,切片主要用于字符串和数组。
字符串切片
- 语法:使用
${str:start:length}
。str="Hello, World!" substr=${str:0:5} # 获取前5个字符
数组切片
- 语法:使用
${array[@]:start:length}
。array=("Alice" "Bob" "Charlie" "David") subarray=("${array[@]:1:2}") # 获取第2到第3个元素
示例
#!/bin/bash
# 字符串切片
str="Hello, World!"
substr=${str:0:5}
echo "Substring: $substr"
# 数组切片
array=("Alice" "Bob" "Charlie" "David")
subarray=("${array[@]:1:2}")
echo "Subarray: ${subarray[@]}"
2. Python 中的切片
在 Python 中,切片用于字符串、列表、元组等序列类型。
字符串切片
- 语法:使用
str[start:end:step]
。str = "Hello, World!" substr = str[0:5] # 获取前5个字符
- 步长:使用
step
参数。substr = str[::2] # 每隔一个字符取一个
列表切片
- 语法:使用
list[start:end:step]
。list = ["Alice", "Bob", "Charlie", "David"] sublist = list[1:3] # 获取第2到第3个元素
示例
# 字符串切片
str = "Hello, World!"
substr = str[0:5]
print("Substring:", substr)
# 列表切片
list = ["Alice", "Bob", "Charlie", "David"]
sublist = list[1:3]
print("Sublist:", sublist)
# 步长切片
substr_step = str[::2]
print("Step slicing:", substr_step)
3. Golang 中的切片
在 Golang 中,切片是动态数组,支持灵活的切片操作。
字符串切片
- 语法:使用
str[start:end]
。str := "Hello, World!" substr := str[0:5] // 获取前5个字符
切片类型
- 语法:使用
slice[start:end]
。slice := []string{"Alice", "Bob", "Charlie", "David"} subslice := slice[1:3] // 获取第2到第3个元素
示例
package main
import "fmt"
func main() {// 字符串切片str := "Hello, World!"substr := str[0:5]fmt.Println("Substring:", substr)// 切片类型slice := []string{"Alice", "Bob", "Charlie", "David"}subslice := slice[1:3]fmt.Println("Subslice:", subslice)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
字符串切片 | ${str:start:length} |
str[start:end:step] |
str[start:end] |
数组/列表切片 | ${array[@]:start:length} |
list[start:end:step] |
slice[start:end] |
步长支持 | 不支持 | 支持 | 不支持 |
索引从 0 开始 | 是 | 是 | 是 |
支持负索引 | 否 | 是 | 否 |
类型安全 | 无 | 动态类型 | 静态类型 |
最佳实践
- 边界检查:
- 在 Golang 中,确保切片范围在有效范围内,否则会引发运行时错误。
- 在 Python 中,使用负索引时注意其含义(从末尾开始计数)。
- 性能优化:
- 在 Golang 中,切片是引用类型,修改子切片会影响原切片。
- 在 Python 中,切片操作返回一个新的序列,不会修改原序列。
- 代码简洁:
- 在 Python 中,使用步长切片简化代码。
- 在 Golang 中,使用切片代替数组以提高灵活性。
示例
Shell
#!/bin/bash
# 字符串切片
str="Hello, World!"
substr=${str:0:5}
echo "Substring: $substr"
# 数组切片
array=("Alice" "Bob" "Charlie" "David")
subarray=("${array[@]:1:2}")
echo "Subarray: ${subarray[@]}"
Python
# 字符串切片
str = "Hello, World!"
substr = str[0:5]
print("Substring:", substr)
# 列表切片
list = ["Alice", "Bob", "Charlie", "David"]
sublist = list[1:3]
print("Sublist:", sublist)
# 步长切片
substr_step = str[::2]
print("Step slicing:", substr_step)
Golang
package main
import "fmt"
func main() {// 字符串切片str := "Hello, World!"substr := str[0:5]fmt.Println("Substring:", substr)// 切片类型slice := []string{"Alice", "Bob", "Charlie", "David"}subslice := slice[1:3]fmt.Println("Subslice:", subslice)
}
正则表达式
1. Shell 中的正则表达式
在 Shell 中,正则表达式通常与 grep
、sed
、awk
等工具结合使用。
匹配
- 语法:使用
grep
。echo "Hello, World!" | grep -E "Hello"
替换
- 语法:使用
sed
。echo "Hello, World!" | sed 's/Hello/Hi/'
分割
- 语法:使用
awk
。echo "Hello,World,Shell" | awk -F, '{print $1, $2, $3}'
示例
#!/bin/bash
# 匹配
echo "Hello, World!" | grep -E "Hello"
# 替换
echo "Hello, World!" | sed 's/Hello/Hi/'
# 分割
echo "Hello,World,Shell" | awk -F, '{print $1, $2, $3}'
2. Python 中的正则表达式
在 Python 中,正则表达式通过 re
模块实现。
匹配
- 语法:使用
re.match()
或re.search()
。import re result = re.search(r"Hello", "Hello, World!")
替换
- 语法:使用
re.sub()
。result = re.sub(r"Hello", "Hi", "Hello, World!")
分割
- 语法:使用
re.split()
。result = re.split(r",", "Hello,World,Python")
示例
import re
# 匹配
match = re.search(r"Hello", "Hello, World!")
if match:print("Match found:", match.group())
# 替换
result = re.sub(r"Hello", "Hi", "Hello, World!")
print("Replaced string:", result)
# 分割
result = re.split(r",", "Hello,World,Python")
print("Split result:", result)
3. Golang 中的正则表达式
在 Golang 中,正则表达式通过 regexp
包实现。
匹配
- 语法:使用
regexp.MatchString()
或regexp.FindString()
。matched, _ := regexp.MatchString(`Hello`, "Hello, World!")
替换
- 语法:使用
regexp.ReplaceAllString()
。result := regexp.MustCompile(`Hello`).ReplaceAllString("Hello, World!", "Hi")
分割
- 语法:使用
regexp.Split()
。result := regexp.MustCompile(`,`).Split("Hello,World,Golang", -1)
示例
package main
import ("fmt""regexp"
)
func main() {// 匹配matched, _ := regexp.MatchString(`Hello`, "Hello, World!")fmt.Println("Match found:", matched)// 替换result := regexp.MustCompile(`Hello`).ReplaceAllString("Hello, World!", "Hi")fmt.Println("Replaced string:", result)// 分割resultSplit := regexp.MustCompile(`,`).Split("Hello,World,Golang", -1)fmt.Println("Split result:", resultSplit)
}
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
匹配 | grep |
re.match() 或 re.search() |
regexp.MatchString() 或 regexp.FindString() |
替换 | sed |
re.sub() |
regexp.ReplaceAllString() |
分割 | awk |
re.split() |
regexp.Split() |
正则表达式语法 | 基本支持 | 完整支持 | 完整支持 |
性能 | 高效 | 中等 | 高效 |
最佳实践
- 正则表达式语法:
- 在 Python 和 Golang 中,使用原始字符串(
r""
或` `
)避免转义问题。 - 在 Shell 中,使用
-E
选项启用扩展正则表达式。
- 在 Python 和 Golang 中,使用原始字符串(
- 性能优化:
- 在 Golang 中,使用
regexp.MustCompile()
预编译正则表达式以提高性能。 - 在 Python 中,使用
re.compile()
预编译正则表达式。
- 在 Golang 中,使用
- 错误处理:
- 在 Golang 中,检查正则表达式编译和匹配的错误。
- 在 Python 中,使用
try-except
捕获异常。
示例
Shell
#!/bin/bash
# 匹配
echo "Hello, World!" | grep -E "Hello"
# 替换
echo "Hello, World!" | sed 's/Hello/Hi/'
# 分割
echo "Hello,World,Shell" | awk -F, '{print $1, $2, $3}'
Python
import re
# 匹配
match = re.search(r"Hello", "Hello, World!")
if match:print("Match found:", match.group())
# 替换
result = re.sub(r"Hello", "Hi", "Hello, World!")
print("Replaced string:", result)
# 分割
result = re.split(r",", "Hello,World,Python")
print("Split result:", result)
Golang
package main
import ("fmt""regexp"
)
func main() {// 匹配matched, _ := regexp.MatchString(`Hello`, "Hello, World!")fmt.Println("Match found:", matched)// 替换result := regexp.MustCompile(`Hello`).ReplaceAllString("Hello, World!", "Hi")fmt.Println("Replaced string:", result)// 分割resultSplit := regexp.MustCompile(`,`).Split("Hello,World,Golang", -1)fmt.Println("Split result:", resultSplit)
}
数据库编程(MySQL、PostgreSQL)
1. Python 中的数据库编程
在 Python 中,常用的数据库接口是 DB-API
,具体实现包括 mysql-connector-python
和 psycopg2
。
操作 MySQL
- 安装库:
pip install mysql-connector-python
- 连接数据库:
import mysql.connector conn = mysql.connector.connect(host="localhost",user="root",password="password",database="testdb" )
- 执行查询:
cursor = conn.cursor() cursor.execute("SELECT * FROM users") rows = cursor.fetchall() for row in rows:print(row)
- 插入数据:
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 30)) conn.commit()
操作 PostgreSQL
- 安装库:
pip install psycopg2
- 连接数据库:
import psycopg2 conn = psycopg2.connect(host="localhost",user="postgres",password="password",database="testdb" )
- 执行查询:
cursor = conn.cursor() cursor.execute("SELECT * FROM users") rows = cursor.fetchall() for row in rows:print(row)
- 插入数据:
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 30)) conn.commit()
示例
# MySQL 示例
import mysql.connector
conn = mysql.connector.connect(host="localhost",user="root",password="password",database="testdb"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:print(row)
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 30))
conn.commit()
conn.close()
# PostgreSQL 示例
import psycopg2
conn = psycopg2.connect(host="localhost",user="postgres",password="password",database="testdb"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:print(row)
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 30))
conn.commit()
conn.close()
2. Golang 中的数据库编程
在 Golang 中,常用的数据库接口是 database/sql
,具体实现包括 mysql
和 pq
。
操作 MySQL
- 安装库:
go get -u github.com/go-sql-driver/mysql
- 连接数据库:
import ("database/sql"_ "github.com/go-sql-driver/mysql" ) db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/testdb")
- 执行查询:
rows, err := db.Query("SELECT * FROM users") for rows.Next() {var id intvar name stringvar age introws.Scan(&id, &name, &age)fmt.Println(id, name, age) }
- 插入数据:
result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 30)
操作 PostgreSQL
- 安装库:
go get -u github.com/lib/pq
- 连接数据库:
import ("database/sql"_ "github.com/lib/pq" ) db, err := sql.Open("postgres", "user=postgres password=password dbname=testdb sslmode=disable")
- 执行查询:
rows, err := db.Query("SELECT * FROM users") for rows.Next() {var id intvar name stringvar age introws.Scan(&id, &name, &age)fmt.Println(id, name, age) }
- 插入数据:
result, err := db.Exec("INSERT INTO users (name, age) VALUES ($1, $2)", "Alice", 30)
示例
// MySQL 示例
package main
import ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)
func main() {db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/testdb")if err != nil {panic(err)}defer db.Close()rows, err := db.Query("SELECT * FROM users")if err != nil {panic(err)}for rows.Next() {var id intvar name stringvar age introws.Scan(&id, &name, &age)fmt.Println(id, name, age)}result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 30)if err != nil {panic(err)}fmt.Println(result.LastInsertId())
}
// PostgreSQL 示例
package main
import ("database/sql""fmt"_ "github.com/lib/pq"
)
func main() {db, err := sql.Open("postgres", "user=postgres password=password dbname=testdb sslmode=disable")if err != nil {panic(err)}defer db.Close()rows, err := db.Query("SELECT * FROM users")if err != nil {panic(err)}for rows.Next() {var id intvar name stringvar age introws.Scan(&id, &name, &age)fmt.Println(id, name, age)}result, err := db.Exec("INSERT INTO users (name, age) VALUES ($1, $2)", "Alice", 30)if err != nil {panic(err)}fmt.Println(result.LastInsertId())
}
对比总结
特性 | Python (MySQL) | Python (PostgreSQL) | Golang (MySQL) | Golang (PostgreSQL) |
---|---|---|---|---|
库名 | mysql-connector-python |
psycopg2 |
github.com/go-sql-driver/mysql |
github.com/lib/pq |
连接字符串 | host, user, password, database |
host, user, password, database |
user:password@tcp(host:port)/db |
user=user password=password dbname=db sslmode=disable |
查询 | cursor.execute() |
cursor.execute() |
db.Query() |
db.Query() |
插入 | cursor.execute() |
cursor.execute() |
db.Exec() |
db.Exec() |
事务 | conn.commit() |
conn.commit() |
db.Begin() |
db.Begin() |
错误处理 | try-except |
try-except |
if err != nil |
if err != nil |
最佳实践
- 连接池:
- 在 Golang 中,
database/sql
默认支持连接池。 - 在 Python 中,使用
mysql-connector-python
或psycopg2
的连接池功能。
- 在 Golang 中,
- 事务管理:
- 在 Golang 中,使用
db.Begin()
和tx.Commit()
管理事务。 - 在 Python 中,使用
conn.commit()
提交事务。
- 在 Golang 中,使用
- 错误处理:
- 在 Golang 中,检查每个操作的错误。
- 在 Python 中,使用
try-except
捕获异常。
示例
Python (MySQL)
import mysql.connector
conn = mysql.connector.connect(host="localhost",user="root",password="password",database="testdb"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:print(row)
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 30))
conn.commit()
conn.close()
Python (PostgreSQL)
import psycopg2
conn = psycopg2.connect(host="localhost",user="postgres",password="password",database="testdb"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:print(row)
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 30))
conn.commit()
conn.close()
Golang (MySQL)
package main
import ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)
func main() {db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/testdb")if err != nil {panic(err)}defer db.Close()rows, err := db.Query("SELECT * FROM users")if err != nil {panic(err)}for rows.Next() {var id intvar name stringvar age introws.Scan(&id, &name, &age)fmt.Println(id, name, age)}result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 30)if err != nil {panic(err)}fmt.Println(result.LastInsertId())
}
Golang (PostgreSQL)
package main
import ("database/sql""fmt"_ "github.com/lib/pq"
)
func main() {db, err := sql.Open("postgres", "user=postgres password=password dbname=testdb sslmode=disable")if err != nil {panic(err)}defer db.Close()rows, err := db.Query("SELECT * FROM users")if err != nil {panic(err)}for rows.Next() {var id intvar name stringvar age introws.Scan(&id, &name, &age)fmt.Println(id, name, age)}result, err := db.Exec("INSERT INTO users (name, age) VALUES ($1, $2)", "Alice", 30)if err != nil {panic(err)}fmt.Println(result.LastInsertId())
}
多进程编程
1. 创建进程
Shell
- 语法:使用
&
实现后台运行,使用wait
等待进程结束。command & wait
- 示例:
#!/bin/bash worker() {echo "Worker $1 is running"sleep 2 } for i in {1..3}; doworker "Process-$i" & done wait echo "All workers are done"
Python
- 语法:使用
multiprocessing.Process
。from multiprocessing import Process def worker(name):print(f"Worker {name} is running") if __name__ == "__main__":p = Process(target=worker, args=("Alice",))p.start()p.join()
- 示例:
from multiprocessing import Process def worker(name):print(f"Worker {name} is running") if __name__ == "__main__":processes = []for i in range(3):p = Process(target=worker, args=(f"Process-{i}",))processes.append(p)p.start()for p in processes:p.join()
Golang
- 语法:使用
go
关键字启动goroutine
。go func() {fmt.Println("Worker is running") }()
- 示例:
package main import ("fmt""sync" ) func worker(wg *sync.WaitGroup, name string) {defer wg.Done()fmt.Printf("Worker %s is running\n", name) } func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1)go worker(&wg, fmt.Sprintf("Process-%d", i))}wg.Wait()fmt.Println("All workers are done") }
2. 进程池
Shell
- 语法:通过控制后台进程数量实现。
max_jobs=3 for i in {1..10}; dowhile [ $(jobs -r | wc -l) -ge $max_jobs ]; dosleep 1doneworker "Process-$i" & done wait
Python
- 语法:使用
multiprocessing.Pool
。from multiprocessing import Pool def worker(name):return f"Worker {name} is done" if __name__ == "__main__":with Pool(3) as pool:results = pool.map(worker, ["Alice", "Bob", "Charlie"])print(results)
Golang
- 语法:使用
channel
控制并发数量。package main import ("fmt""sync" ) func worker(wg *sync.WaitGroup, name string) {defer wg.Done()fmt.Printf("Worker %s is running\n", name) } func main() {var wg sync.WaitGroupmaxJobs := 3jobChan := make(chan struct{}, maxJobs)for i := 1; i <= 10; i++ {wg.Add(1)jobChan <- struct{}{}go func(i int) {defer func() { <-jobChan }()worker(&wg, fmt.Sprintf("Process-%d", i))}(i)}wg.Wait() }
3. 进程间通信
Shell
- 语法:使用文件或命名管道(FIFO)。
mkfifo my_pipe worker() {echo "Hello from worker $1" > my_pipe } for i in {1..3}; doworker "Process-$i" & done for i in {1..3}; doread line < my_pipeecho $line done rm my_pipe
Python
- 语法:使用
multiprocessing.Queue
。from multiprocessing import Process, Queue def worker(q):q.put("Hello from worker") if __name__ == "__main__":q = Queue()processes = []for i in range(3):p = Process(target=worker, args=(q,))processes.append(p)p.start()for p in processes:p.join()while not q.empty():print(q.get())
Golang
- 语法:使用
channel
。package main import ("fmt""sync" ) func worker(wg *sync.WaitGroup, ch chan string, name string) {defer wg.Done()ch <- fmt.Sprintf("Hello from worker %s", name) } func main() {var wg sync.WaitGroupch := make(chan string, 3)for i := 1; i <= 3; i++ {wg.Add(1)go worker(&wg, ch, fmt.Sprintf("Process-%d", i))}wg.Wait()close(ch)for msg := range ch {fmt.Println(msg)} }
对比总结
特性 | Shell | Python | Golang |
---|---|---|---|
创建进程 | & |
multiprocessing.Process |
go |
进程池 | 控制后台进程数量 | multiprocessing.Pool |
channel 控制并发数量 |
进程间通信 | 文件或命名管道 | multiprocessing.Queue |
channel |
性能 | 中等 | 中等 | 高效 |
复杂性 | 低 | 中等 | 中等 |
最佳实践
- 资源管理:
- 在 Shell 中,使用
wait
确保所有后台进程完成。 - 在 Python 中,使用
join()
等待进程结束。 - 在 Golang 中,使用
sync.WaitGroup
等待所有goroutine
完成。
- 在 Shell 中,使用
- 任务分配:
- 在 Shell 中,通过循环和条件判断控制并发数量。
- 在 Python 中,使用
Pool.map()
或Pool.apply_async()
分配任务。 - 在 Golang 中,使用
channel
实现任务队列。
- 错误处理:
- 在 Shell 中,检查命令返回值。
- 在 Python 中,使用
try-except
捕获异常。 - 在 Golang 中,使用
defer
和recover
处理异常。
示例
Shell
#!/bin/bash
worker() {echo "Worker $1 is running"sleep 2
}
for i in {1..3}; doworker "Process-$i" &
done
wait
echo "All workers are done"
Python
from multiprocessing import Process
def worker(name):print(f"Worker {name} is running")
if __name__ == "__main__":processes = []for i in range(3):p = Process(target=worker, args=(f"Process-{i}",))processes.append(p)p.start()for p in processes:p.join()
Golang
package main
import ("fmt""sync"
)
func worker(wg *sync.WaitGroup, name string) {defer wg.Done()fmt.Printf("Worker %s is running\n", name)
}
func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1)go worker(&wg, fmt.Sprintf("Process-%d", i))}wg.Wait()fmt.Println("All workers are done")
}
线程编程
1. 什么是线程?
- 线程 是操作系统能够进行运算调度的最小单位,是进程中的一个执行流。
- 一个进程可以包含多个线程,所有线程共享进程的内存空间和资源。
- 线程比进程更轻量,创建和切换的开销更小。
2. 创建线程
Python
- 语法:使用
threading.Thread
。import threading def worker():print("Worker thread is running") if __name__ == "__main__":t = threading.Thread(target=worker)t.start()t.join()
Golang
- 语法:使用
goroutine
。package main import ("fmt""time" ) func worker() {fmt.Println("Worker goroutine is running") } func main() {go worker()time.Sleep(time.Second) // 等待 goroutine 完成 }
3. 线程间通信
Python
- 语法:使用
queue.Queue
。import threading import queue def worker(q):q.put("Hello from worker") if __name__ == "__main__":q = queue.Queue()t = threading.Thread(target=worker, args=(q,))t.start()t.join()print(q.get())
Golang
- 语法:使用
channel
。package main import "fmt" func worker(ch chan string) {ch <- "Hello from worker" } func main() {ch := make(chan string)go worker(ch)fmt.Println(<-ch) }
4. 什么是互斥锁?
- 互斥锁(Mutex) 是一种同步机制,用于防止多个线程同时访问共享资源。
- 当一个线程持有锁时,其他线程必须等待锁释放后才能访问共享资源。
5. 使用互斥锁
Python
- 语法:使用
threading.Lock
。import threading counter = 0 lock = threading.Lock() def worker():global counterwith lock:counter += 1 if __name__ == "__main__":threads = []for _ in range(10):t = threading.Thread(target=worker)threads.append(t)t.start()for t in threads:t.join()print("Counter:", counter)
Golang
- 语法:使用
sync.Mutex
。package main import ("fmt""sync" ) var (counter intlock sync.Mutex ) func worker(wg *sync.WaitGroup) {defer wg.Done()lock.Lock()counter++lock.Unlock() } func main() {var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go worker(&wg)}wg.Wait()fmt.Println("Counter:", counter) }
6. 多线程死锁以及解决方案
什么是死锁?
- 死锁 是指多个线程互相等待对方释放锁,导致所有线程都无法继续执行。
- 死锁的四个必要条件:
- 互斥条件:资源一次只能被一个线程占用。
- 占有并等待:线程持有资源并等待其他资源。
- 不可抢占:资源只能由持有它的线程释放。
- 循环等待:线程之间形成循环等待资源的关系。
解决方案
- 避免嵌套锁:尽量减少锁的嵌套使用。
- 按顺序加锁:所有线程按相同的顺序获取锁。
- 使用超时机制:为锁设置超时时间,避免无限等待。
- 使用死锁检测工具:如 Python 的
threading
模块或 Golang 的pprof
工具。
7. 线程需要注意的点
- 线程安全:
- 确保共享资源的访问是线程安全的,使用锁或其他同步机制。
- 资源竞争:
- 避免多个线程同时修改同一数据,导致数据不一致。
- 性能开销:
- 线程的创建和切换有一定开销,避免创建过多线程。
- 死锁和活锁:
- 避免死锁和活锁(线程不断重试但无法取得进展)。
- 线程间通信:
- 使用队列、管道或共享内存等方式实现线程间通信。
- 全局解释器锁(GIL):
- 在 Python 中,GIL 限制了多线程的并行执行,建议使用多进程或异步编程提高性能。
示例
Python
import threading
import queue
counter = 0
lock = threading.Lock()
def worker(q):global counterwith lock:counter += 1q.put(f"Worker {threading.current_thread().name} is done")
if __name__ == "__main__":q = queue.Queue()threads = []for i in range(3):t = threading.Thread(target=worker, args=(q,))threads.append(t)t.start()for t in threads:t.join()while not q.empty():print(q.get())print("Counter:", counter)
Golang
package main
import ("fmt""sync"
)
var (counter intlock sync.Mutex
)
func worker(wg *sync.WaitGroup, ch chan string) {defer wg.Done()lock.Lock()counter++lock.Unlock()ch <- "Worker is done"
}
func main() {var wg sync.WaitGroupch := make(chan string, 3)for i := 0; i < 3; i++ {wg.Add(1)go worker(&wg, ch)}wg.Wait()close(ch)for msg := range ch {fmt.Println(msg)}fmt.Println("Counter:", counter)
}
异常处理
1. 什么是异常?
- 异常 是程序执行过程中发生的错误或意外情况,它会中断程序的正常流程。
- 异常通常由以下原因引起:
- 代码逻辑错误(如除以零、访问不存在的索引)。
- 外部因素(如文件不存在、网络连接失败)。
- 用户输入错误(如输入格式不正确)。
- 异常处理是捕获并处理这些错误,使程序能够继续运行或优雅地退出。
2. 异常处理语句
Python
- 语法:使用
try-except-finally
。try:# 可能引发异常的代码result = 10 / 0 except ZeroDivisionError as e:# 捕获特定异常print(f"Error: {e}") except Exception as e:# 捕获所有异常print(f"Unexpected error: {e}") else:# 没有异常时执行print("No error occurred") finally:# 无论是否发生异常都会执行print("Cleanup code")
- 特点:
try
:包含可能引发异常的代码。except
:捕获并处理异常。else
:没有异常时执行。finally
:无论是否发生异常都会执行。
Golang
- 语法:使用
defer
、panic
和recover
。package main import "fmt" func main() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()// 可能引发 panic 的代码panic("Something went wrong") }
- 特点:
panic
:引发异常。recover
:捕获异常。defer
:延迟执行,通常用于资源清理。
Shell
- 语法:使用
trap
捕获信号或错误。#!/bin/bash trap "echo 'Error occurred'; exit 1" ERR # 可能引发错误的代码 ls /nonexistent
- 特点:
trap
:捕获信号或错误并执行指定命令。ERR
:捕获命令执行失败的错误。
3. 异常处理的最佳实践
- 捕获特定异常:
- 尽量捕获特定异常,而不是捕获所有异常,以便更好地处理问题。
- 资源清理:
- 使用
finally
(Python)或defer
(Golang)确保资源被正确释放。
- 使用
- 日志记录:
- 在捕获异常时记录日志,便于调试和排查问题。
- 避免滥用异常:
- 不要使用异常处理控制正常流程,异常应仅用于处理意外情况。
- 用户友好提示:
- 在捕获异常时向用户提供清晰友好的错误信息。
示例
Python
try:result = 10 / 0
except ZeroDivisionError as e:print(f"Error: {e}")
except Exception as e:print(f"Unexpected error: {e}")
else:print("No error occurred")
finally:print("Cleanup code")
Golang
package main
import "fmt"
func main() {defer func() {if r := recover(); r != nil {fmt.Println("Recovered from panic:", r)}}()panic("Something went wrong")
}
Shell
#!/bin/bash
trap "echo 'Error occurred'; exit 1" ERR
ls /nonexistent
对比总结
特性 | Python | Golang | Shell |
---|---|---|---|
异常处理语句 | try-except-finally |
defer , panic , recover |
trap |
捕获特定异常 | except |
recover |
trap |
资源清理 | finally |
defer |
trap |
异常引发 | raise |
panic |
exit |
用户友好提示 | 支持 | 支持 | 支持 |
Docker自动化调用
1. Docker API 的种类与启用
种类
- Docker Engine API:
- 用于与 Docker 守护进程交互,支持容器、镜像、网络等操作。
- 默认端口:
2375
(HTTP)或2376
(HTTPS)。
- Docker Registry API:
- 用于与 Docker 镜像仓库交互,支持镜像的上传、下载、删除等操作。
- 默认端口:
5000
(HTTP)或5001
(HTTPS)。
启用
- 启用 Docker Engine API:
- 修改 Docker 配置文件(如
/etc/docker/daemon.json
):{"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"] }
- 重启 Docker 服务:
sudo systemctl restart docker
- 修改 Docker 配置文件(如
- 启用 Docker Registry API:
- 启动 Docker Registry 容器:
docker run -d -p 5000:5000 --name registry registry:2
- 使用 HTTPS 时,配置 TLS 证书。
- 启动 Docker Registry 容器:
2. 操作镜像
使用 Docker Engine API
- 拉取镜像:
curl -X POST "http://localhost:2375/images/create?fromImage=nginx&tag=latest"
- 列出镜像:
curl "http://localhost:2375/images/json"
- 删除镜像:
curl -X DELETE "http://localhost:2375/images/nginx:latest"
使用 Docker Registry API
- 列出镜像标签:
curl "http://localhost:5000/v2/nginx/tags/list"
- 删除镜像:
curl -X DELETE "http://localhost:5000/v2/nginx/manifests/<digest>"
3. 操作容器
使用 Docker Engine API
- 创建容器:
curl -X POST "http://localhost:2375/containers/create" \-H "Content-Type: application/json" \-d '{"Image": "nginx", "HostConfig": {"PortBindings": {"80/tcp": [{"HostPort": "8080"}]}}}'
- 启动容器:
curl -X POST "http://localhost:2375/containers/<container_id>/start"
- 停止容器:
curl -X POST "http://localhost:2375/containers/<container_id>/stop"
- 删除容器:
curl -X DELETE "http://localhost:2375/containers/<container_id>"
4. 客户端和服务端的 TLS 认证
生成证书
- 生成 CA 证书:
openssl genrsa -aes256 -out ca-key.pem 4096 openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
- 生成服务器证书:
openssl genrsa -out server-key.pem 4096 openssl req -subj "/CN=<server_ip>" -sha256 -new -key server-key.pem -out server.csr echo subjectAltName = IP:<server_ip>,IP:127.0.0.1 > extfile.cnf openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
- 生成客户端证书:
openssl genrsa -out client-key.pem 4096 openssl req -subj "/CN=client" -new -key client-key.pem -out client.csr echo extendedKeyUsage = clientAuth > extfile.cnf openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile extfile.cnf
配置 Docker 守护进程
- 修改 Docker 配置文件(如
/etc/docker/daemon.json
):{"tlsverify": true,"tlscacert": "/path/to/ca.pem","tlscert": "/path/to/server-cert.pem","tlskey": "/path/to/server-key.pem","hosts": ["tcp://0.0.0.0:2376"] }
- 重启 Docker 服务:
sudo systemctl restart docker
客户端使用 TLS 认证
- 使用
curl
:curl --cert /path/to/client-cert.pem --key /path/to/client-key.pem --cacert /path/to/ca.pem https://<server_ip>:2376/version
- 使用
docker
客户端:docker --tlsverify --tlscacert=/path/to/ca.pem --tlscert=/path/to/client-cert.pem --tlskey=/path/to/client-key.pem -H=<server_ip>:2376 version
5. 自动化
使用 Python
- 安装 Docker SDK:
pip install docker
- 示例代码:
import docker client = docker.DockerClient(base_url='tcp://localhost:2376', tls=True) # 拉取镜像 client.images.pull('nginx') # 创建容器 container = client.containers.run('nginx', detach=True, ports={'80/tcp': 8080}) # 启动容器 container.start() # 停止容器 container.stop() # 删除容器 container.remove()
使用 Golang
- 安装 Docker SDK:
go get github.com/docker/docker/client
- 示例代码:
package main import ("context""fmt""github.com/docker/docker/api/types""github.com/docker/docker/client" ) func main() {cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())if err != nil {panic(err)}// 拉取镜像_, err = cli.ImagePull(context.Background(), "nginx", types.ImagePullOptions{})if err != nil {panic(err)}// 创建容器resp, err := cli.ContainerCreate(context.Background(), &container.Config{Image: "nginx",}, &container.HostConfig{PortBindings: map[nat.Port][]nat.PortBinding{"80/tcp": {{HostPort: "8080"}},},}, nil, nil, "")if err != nil {panic(err)}// 启动容器if err := cli.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil {panic(err)}// 停止容器if err := cli.ContainerStop(context.Background(), resp.ID, nil); err != nil {panic(err)}// 删除容器if err := cli.ContainerRemove(context.Background(), resp.ID, types.ContainerRemoveOptions{}); err != nil {panic(err)} }
镜像和容器的增删查改
1. 操作镜像
查看镜像
- API 端点:
GET /images/json
- 示例:
curl "http://localhost:2375/images/json"
- 返回结果:
[{"Id": "sha256:...","RepoTags": ["nginx:latest"],"Size": 1337,"Created": 1633036800} ]
下载镜像
- API 端点:
POST /images/create
- 示例:
curl -X POST "http://localhost:2375/images/create?fromImage=nginx&tag=latest"
- 返回结果:
{"status":"Pulling from library/nginx","id":"latest"}
删除镜像
- API 端点:
DELETE /images/{name}
- 示例:
curl -X DELETE "http://localhost:2375/images/nginx:latest"
- 返回结果:
[{"Deleted":"sha256:..."}]
2. 操作容器
创建容器
- API 端点:
POST /containers/create
- 示例:
curl -X POST "http://localhost:2375/containers/create" \-H "Content-Type: application/json" \-d '{"Image": "nginx", "HostConfig": {"PortBindings": {"80/tcp": [{"HostPort": "8080"}]}}}'
- 返回结果:
{"Id":"...","Warnings":[]}
查看容器
- API 端点:
GET /containers/json
- 示例:
curl "http://localhost:2375/containers/json"
- 返回结果:
[{"Id": "...","Names": ["/my_container"],"Image": "nginx","Status": "Up 5 minutes"} ]
启动容器
- API 端点:
POST /containers/{id}/start
- 示例:
curl -X POST "http://localhost:2375/containers/<container_id>/start"
- 返回结果:
(无返回内容)
停止容器
- API 端点:
POST /containers/{id}/stop
- 示例:
curl -X POST "http://localhost:2375/containers/<container_id>/stop"
- 返回结果:
(无返回内容)
删除容器
- API 端点:
DELETE /containers/{id}
- 示例:
curl -X DELETE "http://localhost:2375/containers/<container_id>"
- 返回结果:
(无返回内容)
3. 使用 Docker SDK
Python
- 安装 Docker SDK:
pip install docker
- 示例代码:
import docker client = docker.DockerClient(base_url='tcp://localhost:2375') # 查看镜像 images = client.images.list() for image in images:print(image.tags) # 下载镜像 client.images.pull('nginx') # 删除镜像 client.images.remove('nginx:latest') # 创建容器 container = client.containers.create('nginx', detach=True, ports={'80/tcp': 8080}) # 查看容器 containers = client.containers.list() for container in containers:print(container.name) # 启动容器 container.start() # 停止容器 container.stop() # 删除容器 container.remove()
Golang
- 安装 Docker SDK:
go get github.com/docker/docker/client
- 示例代码:
package main import ("context""fmt""github.com/docker/docker/api/types""github.com/docker/docker/client" ) func main() {cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())if err != nil {panic(err)}// 查看镜像images, err := cli.ImageList(context.Background(), types.ImageListOptions{})if err != nil {panic(err)}for _, image := range images {fmt.Println(image.RepoTags)}// 下载镜像_, err = cli.ImagePull(context.Background(), "nginx", types.ImagePullOptions{})if err != nil {panic(err)}// 删除镜像_, err = cli.ImageRemove(context.Background(), "nginx:latest", types.ImageRemoveOptions{})if err != nil {panic(err)}// 创建容器resp, err := cli.ContainerCreate(context.Background(), &container.Config{Image: "nginx",}, &container.HostConfig{PortBindings: map[nat.Port][]nat.PortBinding{"80/tcp": {{HostPort: "8080"}},},}, nil, nil, "")if err != nil {panic(err)}// 查看容器containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})if err != nil {panic(err)}for _, container := range containers {fmt.Println(container.Names)}// 启动容器if err := cli.ContainerStart(context.Background(), resp.ID, types.ContainerStartOptions{}); err != nil {panic(err)}// 停止容器if err := cli.ContainerStop(context.Background(), resp.ID, nil); err != nil {panic(err)}// 删除容器if err := cli.ContainerRemove(context.Background(), resp.ID, types.ContainerRemoveOptions{}); err != nil {panic(err)} }
对比总结
操作 | API 端点 | Python SDK | Golang SDK |
---|---|---|---|
查看镜像 | GET /images/json |
client.images.list() |
cli.ImageList() |
下载镜像 | POST /images/create |
client.images.pull() |
cli.ImagePull() |
删除镜像 | DELETE /images/{name} |
client.images.remove() |
cli.ImageRemove() |
创建容器 | POST /containers/create |
client.containers.create() |
cli.ContainerCreate() |
查看容器 | GET /containers/json |
client.containers.list() |
cli.ContainerList() |
启动容器 | POST /containers/{id}/start |
container.start() |
cli.ContainerStart() |
停止容器 | POST /containers/{id}/stop |
container.stop() |
cli.ContainerStop() |
删除容器 | DELETE /containers/{id} |
container.remove() |
cli.ContainerRemove() |
Docker 系统管理开发
1. 系统信息获取
获取 Docker 版本信息
- API 端点:
GET /version
- 示例:
curl "http://localhost:2375/version"
- 返回结果:
{"Version": "20.10.7","ApiVersion": "1.41","MinAPIVersion": "1.12","GitCommit": "b0f5bc3","GoVersion": "go1.13.15","Os": "linux","Arch": "amd64" }
获取 Docker 系统信息
- API 端点:
GET /info
- 示例:
curl "http://localhost:2375/info"
- 返回结果:
{"Containers": 10,"Images": 20,"Driver": "overlay2","KernelVersion": "5.4.0-80-generic","OperatingSystem": "Ubuntu 20.04.2 LTS","NCPU": 4,"MemTotal": 16777216000 }
2. 资源监控
获取容器资源使用情况
- API 端点:
GET /containers/{id}/stats
- 示例:
curl "http://localhost:2375/containers/<container_id>/stats"
- 返回结果:
{"cpu_stats": {"cpu_usage": {"total_usage": 123456789}},"memory_stats": {"usage": 104857600} }
获取系统资源使用情况
- API 端点:
GET /system/df
- 示例:
curl "http://localhost:2375/system/df"
- 返回结果:
{"LayersSize": 123456789,"Images": 20,"Containers": 10,"Volumes": 5 }
3. 日志管理
获取容器日志
- API 端点:
GET /containers/{id}/logs
- 示例:
curl "http://localhost:2375/containers/<container_id>/logs"
- 返回结果:
(容器日志内容)
配置日志驱动
- API 端点:
POST /containers/create
- 示例:
curl -X POST "http://localhost:2375/containers/create" \-H "Content-Type: application/json" \-d '{"Image": "nginx", "HostConfig": {"LogConfig": {"Type": "json-file", "Config": {"max-size": "10m", "max-file": "3"}}}}'
4. 网络管理
列出网络
- API 端点:
GET /networks
- 示例:
curl "http://localhost:2375/networks"
- 返回结果:
[{"Id": "...","Name": "bridge","Driver": "bridge","Scope": "local"} ]
创建网络
- API 端点:
POST /networks/create
- 示例:
curl -X POST "http://localhost:2375/networks/create" \-H "Content-Type: application/json" \-d '{"Name": "my_network", "Driver": "bridge"}'
- 返回结果:
{"Id":"...","Warnings":[]}
删除网络
- API 端点:
DELETE /networks/{id}
- 示例:
curl -X DELETE "http://localhost:2375/networks/<network_id>"
5. 存储管理
列出卷
- API 端点:
GET /volumes
- 示例:
curl "http://localhost:2375/volumes"
- 返回结果:
{"Volumes": [{"Name": "my_volume","Driver": "local","Mountpoint": "/var/lib/docker/volumes/my_volume/_data"}] }
创建卷
- API 端点:
POST /volumes/create
- 示例:
curl -X POST "http://localhost:2375/volumes/create" \-H "Content-Type: application/json" \-d '{"Name": "my_volume", "Driver": "local"}'
- 返回结果:
{"Name":"my_volume","Driver":"local","Mountpoint":"/var/lib/docker/volumes/my_volume/_data"}
删除卷
- API 端点:
DELETE /volumes/{name}
- 示例:
curl -X DELETE "http://localhost:2375/volumes/my_volume"
6. 使用 Docker SDK
Python
- 安装 Docker SDK:
pip install docker
- 示例代码:
import docker client = docker.DockerClient(base_url='tcp://localhost:2375') # 获取 Docker 版本信息 print(client.version()) # 获取 Docker 系统信息 print(client.info()) # 获取容器资源使用情况 stats = client.containers.get('<container_id>').stats(stream=False) print(stats) # 获取容器日志 logs = client.containers.get('<container_id>').logs() print(logs) # 创建网络 network = client.networks.create("my_network", driver="bridge") print(network.id) # 创建卷 volume = client.volumes.create(name="my_volume", driver="local") print(volume.name)
Golang
- 安装 Docker SDK:
go get github.com/docker/docker/client
- 示例代码:
package main import ("context""fmt""github.com/docker/docker/api/types""github.com/docker/docker/client" ) func main() {cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())if err != nil {panic(err)}// 获取 Docker 版本信息version, err := cli.ServerVersion(context.Background())if err != nil {panic(err)}fmt.Println(version.Version)// 获取 Docker 系统信息info, err := cli.Info(context.Background())if err != nil {panic(err)}fmt.Println(info.Containers)// 获取容器资源使用情况stats, err := cli.ContainerStats(context.Background(), "<container_id>", false)if err != nil {panic(err)}fmt.Println(stats)// 获取容器日志logs, err := cli.ContainerLogs(context.Background(), "<container_id>", types.ContainerLogsOptions{})if err != nil {panic(err)}fmt.Println(logs)// 创建网络network, err := cli.NetworkCreate(context.Background(), "my_network", types.NetworkCreate{Driver: "bridge",})if err != nil {panic(err)}fmt.Println(network.ID)// 创建卷volume, err := cli.VolumeCreate(context.Background(), types.VolumeCreateRequest{Name: "my_volume",Driver: "local",})if err != nil {panic(err)}fmt.Println(volume.Name) }
对比总结
操作 | API 端点 | Python SDK | Golang SDK |
---|---|---|---|
获取版本信息 | GET /version |
client.version() |
cli.ServerVersion() |
获取系统信息 | GET /info |
client.info() |
cli.Info() |
获取容器资源使用 | GET /containers/{id}/stats |
container.stats() |
cli.ContainerStats() |
获取容器日志 | GET /containers/{id}/logs |
container.logs() |
cli.ContainerLogs() |
创建网络 | POST /networks/create |
client.networks.create() |
cli.NetworkCreate() |
创建卷 | POST /volumes/create |
client.volumes.create() |
cli.VolumeCreate() |