基础代码
项目结构
parent/
__init__.py
one/
__init__.py
two/
__init__.py
three/
__init__.py
sample
README.md
LICENSE
go.mod
go.sum
main.go
util.go 'package main
util_test.go
sample/sample.go 'package sample
/test_sample.go
/other/main.go 'package main 可直接go run或者go build(go build后的可执行文件需要放置在go.mod所在目录下执行)
小技巧
关于internal目录: 无论是哪种类型的Go项目,对于不想暴露给外部引用,仅限项目内部使用的包,可以通过internal包机制来实现。
当然internal也可以放在项目结构中的任一目录层级中。
一个project可以创建多个module
一个module中可以创建多个package
一个package可以创建多个class
HelloWorld
hello.js
console.log('hello Node.js')
$ node hello.js
#include<stdio.h>
int main()
{
printf("你好你好");
return 0;
}
注释
"""模块注释"""
from typing import (
Union, Optional, Any, IO, Iterable, AnyStr, Dict, List, Tuple
)
# 单行注释
def add(a: int, b: int):
"""加法
实现加法的逻辑
:param a: 数值1
:param b: 数值2
:return:
Example
--------
>>> add(1, 2)
"""
return a + b
class Client:
"""Client的简介描述
更多关于Client的信息描述。
此处为段落描述内容 ...
:param object data: 可迭代对象或者IO对象的类型
:param str param1:
字符串参数说明
:param (:obj:`str`, optional) param2:
可选参数说明,类型可能是字符或者字典
:param param3:
可选参数说明, 任意类型
段落说明...
:argument int:
不定参数说明
:keyword str keyword1:
关键字1说明
:keyword float keyword2:
关键字2说明
:keyword bool keyword3: 关键字3说明
See also
--------
参见内容在这里写
Notes
-----
注解内容在这里写
"""
info = [{'id': 1}], [{'active': True}]
def __init__(
self,
data: Union[Iterable[AnyStr], IO[AnyStr]],
param1: str,
param2: Optional[Union[str, Dict[str, Any]]] = None,
param3: Optional[Any] = None,
*args: int,
**kwargs: Any
):
self.data = data
self.param1 = param1
self.param2 = param2
self.param3 = param3
self.args = args
self.kwargs = kwargs
@classmethod
def get_client_info(cls) -> Tuple[List[Dict[str, int]], List[Dict[str, bool]]]:
"""函数功能介绍
:returns:
二元组返回值说明
:rtype:
tuple(list(dict(str, str), list(dict(str, str))
Examples
--------
>>> Client.get_client_info()
([{'id': 1}], [{'active': True}])
"""
return cls.info
/* 多行注释 */
// 单行注释
/* 多行注释 */
// 单行注释
/* 多行注释 */
// 单行注释
{# note: commented-out template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
声明变量
age = 8
# 私有变量
# ====================================
# 使用场景: A类和B类都定义一个run方法,C类同时继承A类和B类,B类使用run方法时可能调用了A类的run方法,这时可以使用私有变量 避免命名冲突问题
class A:
def __run(self):
pass
class B:
def __run(self):
pass
def call_run(self):
self.__run()
class C(A, B):
def __init__(self):
pass
package main
import "fmt"
var age int8 = 8
type A struct{}
// 私有方法
func (a *A) run() {}
func main() {
fmt.Println(age)
a := A{}
a.run()
}
// 声明的同时直接赋值
let age = 18, uname = '迪丽热巴'
常量
PI = 3.14
print(PI)
package main
import "fmt"
const PI = 3.14
type Gender uint
const (
FEMALE Gender = iota
MALE
THIRD
)
func main() {
fmt.Println(PI)
fmt.Println(FEMALE, MALE, THIRD)
}
// 常量
const PI = 3.14
console.log(PI)
字符串
age = 18
print(f"我今年{age}岁了")
name = "黑马程序员"
message = "学IT就来 %s" % name
print(message)
class_num = 57
avg_salary = 16781
message = "Python大数据学科, 北京%s期, 毕业平均工资: %s" % (class_num, avg_salary)
print(message)
"""
其他格式符号
* %s - 将内容转换成字符串,放入占位位置
* %d - 将内容转换成整数,放入占位位置
* %f - 将内容转换成浮点型,放入占位位置
"""
package main
import (
"fmt"
)
func main() {
type simple struct {
value int
}
a := simple{
value: 10,
}
// 通用占位符
fmt.Printf("默认格式的值: %v \n", a)
fmt.Printf("包含字段名的值: %+v \n", a)
fmt.Printf("go语法表示的值: %#v \n", a)
fmt.Printf("go语法表示的类型: %T \n", a)
fmt.Printf("输出字面上的百分号: %%10 \n")
// 整数占位符
v1 := 10
v2 := 20170 // "今" 字码点值
fmt.Printf("二进制: %b \n", v1)
fmt.Printf("Unicode 码点转字符: %c \n", v2)
fmt.Printf("十进制: %d \n", v1)
fmt.Printf("八进制: %o \n", v1)
fmt.Printf("Oo为前缀的八进制: %O \n", v1)
fmt.Printf("用单引号将字符的值抱起来: %q \n", v2)
fmt.Printf("十六进制: %x \n", v1)
fmt.Printf("十六进制大写: %X \n", v1)
fmt.Printf("Unicode格式: %U \n", v2)
// 宽度设置
fmt.Printf("%v 的二进制: %b; go语法表示二进制为: %#b; 指定二进制宽度为8, 不足8位补0: %08b \n", v1, v1, v1, v1)
fmt.Printf("%v 的十六进制: %x; 使用go语法表示为, 指定十六进制宽度为8, 不足8位补0: %#08x \n", v1, v1, v1)
fmt.Printf("%v 的字符位: %c; 指定宽度位5位, 不足5位补空格: %5c \n", v2, v2, v2)
// 浮点数占位符
var f1 = 123.789
var f2 = 12345678910.78999
fmt.Printf("指数为二的幂的无小数科学计数法: %b \n", f1)
fmt.Printf("科学计数法: %e \n", f1)
fmt.Printf("科学计数法, 大写: %E \n", f1)
fmt.Printf("有小数点而无指数, 即常规的浮点数格式。默认宽度和精度: %f \n", f1)
fmt.Printf("宽度为9, 精度默认: %9f \n", f1)
fmt.Printf("默认宽度, 精度保留两位小数: %.2f \n", f1)
fmt.Printf("宽度为9, 精度保留两位小数: %9.2f \n", f1)
fmt.Printf("宽度为9, 精度保留0位小数: %9.f \n", f1)
fmt.Printf("根据情况自动选%%e 或 %%f 来输出, 以产生更紧凑的输出 (末位无0): %g %g \n", f1, f2)
fmt.Printf("根据情况自动选%%E 或 %%f 来输出, 以产生更紧凑的输出 (末位无0): %G %G \n", f1, f2)
fmt.Printf("以十六进制方式表示: %x \n", f1)
// 字符串占位符
var str = "今天是个好日子"
fmt.Printf("描述一下今天: %s \n", str)
// 用双引号将字符串包裹
fmt.Printf("描述一下今天: %q \n", str)
// 16进制表示
fmt.Printf("%x \n", str)
// 以空格作为两数之间的分隔符,并用大写16进制
fmt.Printf("% X \n", str)
// 指针占位符
var str1 = "今天是个好日子"
bytes := []byte(str1)
// 切片第0个元素的地址
fmt.Printf("%p \n", bytes)
mp := make(map[string]int, 0)
fmt.Printf("%p \n", mp)
var p *map[string]int = new(map[string]int)
fmt.Printf("%p \n", p)
}
let age = 18
// 模板字符串
document.write(`我今年${age}岁了`)
列表
# arr = [10, 20, 30]
arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师']
print(arr)
print(arr[0])
print(len(arr))
# 循环
for item in arr:
print(item)
package main
import (
"fmt"
"sort"
)
func main() {
// 定义切片
// ===============================
var slice []int
slice = []int{1, 2, 3, 4, 5, 6}
slice1 := make([]int, 10)
slice1[1] = 10
fmt.Println(slice, slice1)
slice2 := make([]int, 5, 10)
fmt.Println(len(slice2), cap(slice2))
slice2[0] = 0
slice2[1] = 1
slice2[2] = 2
slice2[3] = 3
slice2[4] = 4
// 排序
// =========================================
// https://blog.51cto.com/mouday/11250658
fmt.Println("排序")
fmt.Println("=========================")
sort.Slice(slice2, func(i, j int) bool {
return i > j
})
fmt.Println(slice2)
// 切片截取
// ===================================
slice3 := slice2[1:10]
fmt.Println(len(slice3), cap(slice3), slice3)
// 切片的附加(扩容)
slice3 = append(slice3, 1, 2, 3, 4, 5)
fmt.Println(len(slice3), cap(slice3), slice3)
// 集合, 无序
mp := make(map[string]string, 10)
mp["A"] = "a"
mp["B"] = "b"
mp["C"] = "c"
mp["D"] = "d"
fmt.Println(mp)
// 无序
for k, v := range mp {
fmt.Println(k, v)
}
// 删除集合元素
delete(mp, "B")
fmt.Println(mp)
// 最大值最小值
fmt.Println(max(1, 2, 3, 5, 4))
fmt.Println(min(1, 2, 3, 5, 4))
}
// let arr = [10, 20, 30,]
// 1. 声明数组
let arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师']
// 2. 使用数组
console.log(arr)
console.log(arr[0])
// 3. 数组长度
console.log(arr.length)
元组
"""
演示tuple元组的定义和操作
"""
# 定义元组
t1 = (1, "Hello", True)
t2 = ()
t3 = tuple()
print(f"t1的类型是: {type(t1)}, 内容是: {t1}")
print(f"t1的类型是: {type(t2)}, 内容是: {t2}")
print(f"t1的类型是: {type(t3)}, 内容是: {t3}")
# 定义单个元素的元素
t4 = ("hello", )
print(f"t1的类型是: {type(t4)}, 内容是: {t4}")
# 元组的嵌套
t5 = ((1, 2, 3), (4, 5, 6))
print(f"t1的类型是: {type(t5)}, 内容是: {t5}")
# 下表索引去取出内容
num = t5[1][2]
print(f"从嵌套元组中取的数据是: {num}")
# 元组的操作: index查找方法
t6 = ("传智教育", "黑马程序员", "Python")
index = t6.index("黑马程序员")
print(f"在元组t6中查找黑马程序员,的下标是: {index}")
# 元组的操作: count统计方法
t7 = ("传智教育", "黑马程序员", "黑马程序员", "黑马程序员", "Python")
num = t7.count("黑马程序员")
print(f"在元组t7中统计黑马程序员的数量有: {num}个")
# 元组的操作: len函数统计元组元素数量
t8 = ("传智教育", "黑马程序员", "黑马程序员", "黑马程序员", "Python")
num = len(t8)
print(f"t8元组中的元素有: {num}")
# 元组的遍历: while
index = 0
while index < len(t8):
print(f"元组的元素有: {t8[index]}")
index += 1
# 元组的遍历: for
for element in t8:
print(f"元组的元素有: {element}")
# 修改元组内容
t9 = (1, 2, ["itheima", "itcast"])
print(f"t9的内容是: {t9}")
t9[2][0] = "黑马程序员"
t9[2][1] = "传智教育"
print(f"t9的内容是: {t9}")
字典
"""
演示数据容器字典的定义
"""
# 定义字典
my_dict = {"王力鸿": 99, "周杰轮": 88, "林俊节": 77}
# 从字典中基于Key获取Value
score = my_dict["王力鸿"]
print(f"王力鸿的考试分数是: {score}")
"""
演示字典的常用操作
"""
my_dict = {"周杰轮": 99, "林俊节": 88, "张学油": 77}
# 新增元素
my_dict["张信哲"] = 66
print(my_dict)
# 更新元素
my_dict["周杰轮"] = 33
# 删除元素
score = my_dict.pop("周杰轮")
print(score)
# 清空元素
my_dict.clear()
# 获取全部的Key
my_dict = {"周杰轮": 99, "林俊节": 88, "张学油": 77}
keys = my_dict.keys()
print(keys)
# 遍历字典
for key in keys:
print(my_dict[key])
# 统计字典内的元素数量
num = len(my_dict)
print(num)
package main
import (
"fmt"
)
var GlobalDict = map[string]int{
"张学友": 99,
"周杰伦": 88,
"林俊杰": 77,
}
func main() {
// 定义字典
myDict := map[string]int{"王力鸿": 99, "周杰轮": 88, "林俊节": 77}
// 从字典中基于Key获取Value
score := myDict["王力鸿"]
fmt.Printf("王力鸿的考试分数是: %v", score)
// 新增元素
myDict["张信哲"] = 66
// 更新元素
myDict["周杰轮"] = 33
// 删除元素
delete(myDict, "周杰轮")
// 清空元素
myDict = make(map[string]int, 0)
// 获取全部的key
keys := make([]string, 0, len(myDict))
for key := range myDict {
keys = append(keys, key)
}
// 遍历字典
for k, v := range myDict {
fmt.Println(k, v)
}
// 实现python的dict.keys和values方法
//maps.Keys() go 1.23版本才支持
//maps.Values()
}
类型系统
s = "pink"
print(type(s))
# ***************类型转换*****************
s = '123'
print(int(123))
/*
https://blog.csdn.net/tekin_cn/article/details/138341028
*/
package main
import (
"fmt"
"reflect"
)
func main() {
s := "pink"
// 打印类型
fmt.Printf("%T", s)
// 通过反射获取类型
fmt.Println("type of s is:", reflect.TypeOf(s))
// 类型断言检测变量类型
var i any = "Hello"
s, ok := i.(string)
if ok {
fmt.Println(s)
}
// 类型选择
switch v := i.(type) {
case string:
fmt.Println(v)
case int:
fmt.Println(v * 2)
default:
fmt.Println("Unknown type")
}
// 类型转换
var a = 100
b := float64(a) //将int型转换成float64型
c := string(rune(a)) //将int型转换成string型
fmt.Println(b, c)
// 浮点型与整型之间转换
// float和int的类型精度不同,使用时需要注意float转int时精度的损失。
chinese := 90
english := 80.9
avg := (chinese + int(english)) / 2
avg2 := (float64(chinese) + english) / 2
fmt.Printf("%T,%d\n", avg, avg) // int,85
fmt.Printf("%T, %f\n", avg2, avg2) // float64, 85.450000
// 整型转字符串类型
/*
这种类型的转换,其实相当于byte或rune转string。int数值是ASCII码的编号或unicode字符集的编号,转成
string就是根据字符集,将对应编号的字符查出来。当该数值超出unicode编号范围,则转成的字符串显示为
乱码。例如,19968转string,就是'一'。
备注:
·ASCII字符集中数字的十进制范围是48~57;
·ASCII字符集中大写字母的十进制范围是65~90;
·ASCII字符集中小写字母的十进制范围是97~122;
·unicode字符集中汉字的范围是4e00~9fa5,十进制范围是19968~40869。
*/
d := 97
x := 19968
result := string(rune(d)) // a
fmt.Println(result)
result = string(rune(x)) // 一
fmt.Println(result)
// 注意:在Go语言中,不允许字符串转int。
}
// 1. true false
console.log(3 > 4) // false
let isCool = true
console.log(isCool)
// 2. 未定义类型
// 未定义类型
let num
console.log(num)
// 3. null 空的
let obj = null
console.log(obj)
console.log(null + 1)
// null和undefined计算有区别
console.log(undefined + 1) // Nan
// 4. 类型检测
console.log(typeof null)
let str = 'pink'
console.log(typeof str)
let str1 = '10'
console.log(typeof str1)
let flag = false
console.log(typeof flag)
let un
console.log(typeof un)
console.log(typeof obj) // object
/* ============= 类型转换 ================ */
console.log(1 + 1)
console.log('pink' + 1)
console.log(2 + 2) // 4
console.log(2 + '2') // '22
console.log(2 - 2) // 0
console.log(2 - '2') // 0
console.log(+12)
console.log(+'123') // 转换为数字型
// 显式转换
let str = '123'
console.log(Number(str))
console.log(Number('pink')) // Nan
// let num = Number(prompt('输入年薪'))
let num = +prompt('输入年薪')
console.log(num)
console.log(parseInt('12px')) // 12
console.log(parseInt('12.94px')) // 12
console.log('abc12.94px') // NaN
// ----------------
console.log(parseFloat('12px')) // 12
console.log(parseFloat('12.34px')) // 12.34
let a: string
let b: number
let c: boolean
// 声明数组
let arr: string[]
let arr2: Array<number>
arr = ['a', 'b']
arr2 = [100, 200]
// 声明对象类型
// ==========================================================================
let person1: { name: string, age?: number }
let person2: {
name: string
// 可选字段
age?: number
}
let person: {
name: string
// 可选字段
age?: number
// 索引签名: 允许定义对象有任意数量的属性,这些属性的键和类型是可变的,常用于描述类型不确定的属性(具有动态属性的对象)
[key: string]: any
}
person1 = {name: '李四', age: 18}
person2 = {name: '王五'}
person = {name: 'tom', age: 18, gender: '男', city: '北京'}
// 声明函数类型
// ====================================================================
// (还可以使用: 接口、自定义类型等方式)
let count: (a: number, b: number) => number
count = (x, y) => {
return x + y
}
// tuple
// =======================================
// 一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。
let arr3: [string, number]
// 第一个元素必须是number, 第二个元素是可选的
let arr4: [number, boolean?]
// 第一个元素必须是number, 后面的元素可以是任意数量的string类型
let arr5: [number, ...string[]]
arr3 = ['hello', 123]
arr4 = [100, false]
arr4 = [200]
arr5 = [100, 'hello', 'world']
arr5 = [100]
// 枚举
// ================================================
// 其成员的值会自动递增,且数字枚举还具备反向映射的特点
enum Direction {
Up,
Down,
Left,
Right
}
function walk(data: Direction){
if (data === Direction.Up){
console.log("向【上】走");
} else if (data === Direction.Down) {
console.log("向【下】走")
} else if (data === Direction.Left) {
console.log("向【左】走")
} else if (data === Direction.Right) {
console.log("向【右】走")
} else {
console.log("未知方向")
}
}
walk(Direction.Down)
// 常量枚举
// ----------------------------------------
// 一种特殊枚举类型,在编译时会被内联,避免生成一些额外的代码
// 内联: 编译时,会将枚举成员引用替换为它们的实际值,而不是生成额外的枚举对象。可以减少生成的javaScript代码量,并提高运行时性能。
/*
* const enum Direction {
Up,
Down,
Left,
Right
}
* */
// type
// ===============================================
type num = number;
let price: num
price = 100
// 联合类型
type Status = number | string
type Gender = '男' | '女'
function printStatus(status: Status) {
console.log(status)
}
function logGender(str: Gender) {
console.log(str)
}
printStatus(404);
printStatus('200');
logGender('男')
logGender('女')
// 交叉类型
// 面积
type Area = {
height: number; // 高
width: number; // 宽
}
// 地址
type Address = {
num: number // 楼号
cell: number // 单元号
room: string // 房间号
}
type House = Area & Address
const house: House = {
height: 100,
width: 100,
num: 3,
cell: 4,
room: '702'
}
反射
package main
import (
"fmt"
"reflect"
)
// Kind https://pkg.go.dev/reflect#Kind
func Kind() {
for _, v := range []any{"hi", 42, func() {}} {
switch v := reflect.ValueOf(v); v.Kind() {
case reflect.String: // 判断是字符串类型
fmt.Println(v.String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
fmt.Println(v.Int())
default:
fmt.Printf("unhandled kind %s", v.Kind())
}
}
}
func main() {
fmt.Println("Kind")
fmt.Println("==============================")
Kind()
}
参见
应用案例:
Json.Marshal, 入参v是any, reflect.ValueOf(v), 然后用到reflect的各种api去判断和处理
警告
慎用reflect包
虽然提供了强大的功能,但是它可能会带来一定的性能开销。因此,在可能的情况下,考虑使用类型断言或者泛型代替
过度依赖reflect可能会使得代码难以理解和维护
类型声明文件
typescript中的一种特殊文件,通常以.d.ts作为拓展名。它的主要作用是为现有的JavaScript代码提供类型信息
export function add(a, b){
return a + b;
}
export function mul(a, b){
return a * b
}
declare function add(a: number, b: number): number;
declare function mul(a: number, b: number): number;
export {add, mul};
条件判断
def if_else_case(a: int):
if a == 0:
print("执行 if 语句块")
elif a == 1:
print("执行 else if 语句块")
else:
print("执行 else 语句块")
package main
import "fmt"
func ifElseCase(a int) {
if a == 0 {
fmt.Println("执行 if 语句块")
} else if a == 1 {
fmt.Println("执行 else if 语句块")
} else {
fmt.Println("执行 else 语句块")
}
// 特殊写法
// 需要注意的是,num的定义在if里,那么只能够在该if...else语句块中使用,否则编译器会报错。
if num := a; num%2 == 0 {
fmt.Println(num, "偶数")
} else {
fmt.Println(num, "奇数")
}
}
func main() {
ifElseCase(0)
}
CREATE FUNCTION if_else_case(a int) returns varchar(64)
BEGIN
IF (a = 0) THEN
return '执行 if 语句块';
ELSEIF (a = 1) THEN
return '执行 else if 语句块';
ELSE
return '执行 else 语句块';
END IF;
END
循环
for i in range(10): if i == 5: continue print("位置1 执行 for 语句块 i:", i) i = 0 b = True while b: print("位置2 执行 for 语句块 i:", i) i += 1 if i >= 10: b = False # 列表循环 LIST = [1, 2, 3, 4, 5, 6, 7, 8, 9] for index, data in enumerate(LIST): print("位置3 执行 for 语句块 index: {}, data: {}".format(index, data)) # 字典循环 mp = {"A": "a", "B": "b", "C": "c"} for key, value in mp.items(): print("位置4 执行 for 语句块 key: {}, value: {}".format(index, value)) # 字符串循环 STR = "今天天气很好" for index, char in enumerate(STR): print("位置5 执行 for 语句块 key: {}, char: {}".format(index, char)) # 死循环 j = 0 while True: print("位置6 执行死循环 j:", j) j += 1 if j >= 10: breakpackage main import "fmt" func forCase(){ for i := 0; i < 10; i++ { if i == 5 { continue } fmt.Println("位置1 执行 for 语句块 i:", i) } var i int var b = true for b { fmt.Println("位置2 执行 for 语句块 i:", i) i++ if i >= 10 { b = false } } // 切片循环 list := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} for index, data := range list { fmt.Printf("位置3 执行 for 语句块 index: %d, data: %d \n", index, data) } // 字典循环 mp := map[string]string{"A": "a", "B": "b", "C": "c"} for key, value := range mp { fmt.Printf("位置4 执行 for 语句块 key: %v, value: %v \n", key, value) } // 字符串循环 str := "今天天气很好" for index, char := range str { fmt.Printf("位置5 执行 for 语句块 index: %v, char: %v \n", index, string(char)) } var j int for { fmt.Println("位置6 执行 for 语句块 j:", j) j++ if j >= 10 { break } } for i := 0; i < 2; i++ { for j := 0; j < 2; j++ { fmt.Printf("位置7 执行 for 语句块 i: %d, j: %d\n", i, j) } } lab1: for i := 0; i < 2; i++ { for j := 0; j < 2; j++ { fmt.Printf("位置8 执行 for 语句块 i: %d, j: %d\n", i, j) break lab1 } } }while
create procedure proc_statement_while() begin declare var int; set var=0; while var<1 do insert into userinfo values(4, 'zhangsan4', 18); set var=var+1; end while; end;loop
create procedure proc_statement_loop() begin declare v int; set v=0; loop_lable:loop insert into userinfo values(4, 'zhangsan4', 18); set v=v+1; if v >= 1 then leave loop_lable; end if; end loop; end;
switch
# match表面上像C、Java或JavaScript中的switch语句,但其实它更像Rust或Haskell中的模式匹配。
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
package main
import "fmt"
// SwitchCase
// switch语句执行的过程自上而下,直到找到case匹配项,匹配项中无须使用break,因为Go语言
// 中的switch默认给每个case自带break。因此匹配成功后不会向下执行其他的case分支,而是跳出
// 整个switch。可以添加fallthrough,强制执行后面的case分支。fallthrough必须放在case分支的
// 最后一行。如果它出现在中间的某个地方,编译器就会报错。
func SwitchCase(alpha string, in interface{}) {
switch alpha {
case "A":
fmt.Println("执行 A 语句块")
case "B":
fmt.Println("执行 B 语句块")
case "C", "D":
fmt.Println("执行 CD 语句块")
fallthrough
case "E":
fmt.Println("执行 E 语句块")
case "F":
fmt.Println("执行 F 语句块")
}
// switch语句还可以被用于type switch(类型转换)来判断某个interface变量中实际存储的变量类型。
// 下面演示type switch的语法。其语法结构如下所示:
switch in.(type) {
case string:
fmt.Println("in 输入为字符串")
case int:
fmt.Println("in 输入为int类型")
default:
fmt.Println("未能识别in的类型")
}
}
func SwitchOnly(score float64) {
grade := ""
switch { //switch后面省略不写,默认相当于:switch true
case score >= 90:
grade = "A"
case score >= 80:
grade = "B"
case score >= 70:
grade = "C"
case score >= 60:
grade = "D"
default:
grade = "E"
}
switch grade {
case "A":
fmt.Printf("优秀!\n")
case "B":
fmt.Printf("良好\n")
case "C":
fmt.Printf("中等\n")
case "D":
fmt.Printf("及格\n")
default:
fmt.Printf("差\n")
}
}
// JudgeInterface 判断interface变量中存储的变量类型
func JudgeInterface(x interface{}) {
switch i := x.(type) {
case nil:
fmt.Printf(" x 的类型:%T", i)
case int:
fmt.Printf("x是int型")
case float64:
fmt.Printf("x是float64型")
case func(int):
fmt.Printf("x是func(int)型")
case bool, string:
fmt.Printf("x是bool或string型")
default:
fmt.Printf("未知型")
}
}
func main() {
SwitchCase("A", 1)
SwitchOnly(85.5)
JudgeInterface(10)
}
create procedure proc_statement_case (in parameter int)
begin
declare var int;
set var=parameter+1;
case var
when 0 then
insert into userinfo values(4, 'zhangsan4', 18);
when 1 then
insert into userinfo values(5, 'zhangsan5', 18);
else
insert into userinfo values(6, 'zhangsan6', 18);
end case;
end;
异常
import sys
# 处理多个异常
# ==============================
try:
raise RuntimeError
except (RuntimeError, TypeError, NameError):
pass
class HY000(Exception):
pass
def create_synonym_db(db_name):
...
db_err_msg = 'Unknown database ' + db_name
# 抛出自定义异常
raise HY000(db_err_msg)
else子句
try … except 语句有一个可选的 else 子句,在使用时必须放在所有的 except 子句后面。对于在try 子句不引发异常 时必须执行的代码来说很有用。例如:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
finally
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
如果存在 finally 子句,则 finally 子句将作为 try 语句结束前的最后一项任务被执行。 finally 子句不论 try 语句是否产生了异常都会被执行。
异常链
raise 语句允许可选的 from 子句,它启用了链式异常。 例如:
# exc must be exception instance or None.
raise RuntimeError from exc
小技巧
用途: 转换异常
禁用异常链可使用 from None 习语
打印异常内容
import traceback
try:
print(1/0)
except Exception:
# 输出到控制台
traceback.print_exc()
# 保存到变量
err = traceback.format_exc()
package main
import (
"errors"
"fmt"
"log"
"time"
)
type cusError struct {
Code string
Msg string
Time time.Time
}
// Error 实现了error的接口方法
func (err cusError) Error() string {
return fmt.Sprintf("Code:%s,Msg:%s,Time:%s", err.Code, err.Msg, err.Time.Format("2006-01-02T15:04:05Z07:00"))
}
func getCusError(code, msg string) error {
return cusError{
Code: code,
Msg: msg,
Time: time.Now(),
}
}
func ErrorCase() {
err := errors.New("程序发生了错误")
fmt.Println(err)
var a, b = -1, -2
res, err := sum(a, b)
fmt.Println(res, err)
if err != nil {
log.Println(err)
cusErr, ok := err.(cusError)
if ok {
fmt.Println("打印自定义错误信息: ", cusErr.Code, cusErr.Msg, cusErr.Time)
}
}
}
func sum(a, b int) (int, error) {
if a <= 0 && b <= 0 {
return 0, getCusError("500", "两数求和不能同时小于0")
}
return a + b, nil
}
func main() {
ErrorCase()
}
CREATE PROCEDURE p (pval INT)
BEGIN
DECLARE specialty CONDITION FOR SQLSTATE '45000';
IF pval = 0 THEN
# 告警
SIGNAL SQLSTATE '01000';
ELSEIF pval = 1 THEN
# 抛出异常第一种形式
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred';
ELSEIF pval = 2 THEN
# 抛出异常第二种形式
SIGNAL specialty
SET MESSAGE_TEXT = 'An error occurred';
ELSE
SIGNAL SQLSTATE '01000'
SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1000;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001;
END IF;
END;
导包
# 正常导包
import string
# 别名
import string as s
print(string.Template)
print(s.Template)
# 使用from导入time的sleep功能
from time import sleep
print("你好")
sleep(5)
print("我好")
# 使用*导入time模块的全部功能
from time import *
print("你好")
sleep(5)
print("我好")
# 如果一个模块文件中有`__all__`变量, 当使用`from xxx import *`导入时,只能导入这个列表中的元素
# 通过绝对路径导入模块
# ==============================================
import sys
from importlib import import_module
sys.path.insert(0, 'module所在目录的绝对路径')
if 'module' in sys.modules:
# 删除缓存, 避免导入同名的其他模块
del sys.modules['module']
module = import_module('.module', package='module所在目录名')
/*
https://go.dev/ref/spec#Import_declarations
*/
package main
// Basic imports
import (
// 正常导包
"fmt"
// 别名
f "fmt"
)
func main() {
fmt.Println("Hello World")
f.Println("Hello World")
}
函数
str1 = "itheima"
str2 = "itcast"
str3 = "python"
def my_len(data):
"""需求: 统计字符串的长度,不使用内置函数len()"""
count = 0
for i in data:
count += 1
print(f"字符串{data}的长度是{count}")
my_len(str1)
my_len(str2)
my_len(str3)
def user_info(name, age, gender):
print(f"姓名是: {name}, 年龄是: {age}, 性别是: {gender}")
# 位置参数
user_info('小明', 20, '男')
# 关键字参数
user_info(name='小王', age=11, gender='女')
# 缺省参数(默认值)
def user_info(name, age, gender='男'):
print(f"姓名是: {name}, 年龄是: {age}, 性别是: {gender}")
user_info('小天', 13)
# 不定长 - 位置不定长, *号, 会作为元组存在,接收不定长数量的参数
def user_info(*args):
print(f'args参数的类型是: {type(args)}, 内容是: {args}')
user_info(1, 2, 3, '小明', '男孩')
# 关键字不定长, **号
def user_info(**kwargs):
print(f'kwargs参数的类型是: {type(kwargs)}, 内容是: {kwargs}')
user_info(name='小王', age=11, gender='男孩', addr='北京')
# 演示函数作为参数传递
def _test_func(compute):
result = compute(1, 2)
print(f"compute参数的类型是: {type(compute)}")
print(f"计算结果是: {result}")
def compute(x, y):
return x + y
_test_func(compute)
# 演示lambda匿名函数
_test_func(lambda x, y: x + y)
package main
import "fmt"
// MyLen 需求: : 统计字符串的长度,不使用内置函数len()
func MyLen(data string) {
count := 0
for range data {
count += 1
}
fmt.Printf("字符串%s的长度是%d", data, count)
}
func main() {
MyLen("itheima")
MyLen("itcast")
MyLen("python")
}
默认参数
原生不支持默认值, 实现方式可参考testcontainers的开源代码: https://github.com/testcontainers/testcontainers-go/blob/v0.33.0/modules/mysql/mysql.go
使用的例子, 传入可选项参数修改默认值:
package main
import (
"context"
"log"
"path/filepath"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/mysql"
)
func main() {
ctx := context.Background()
mysqlContainer, err := mysql.Run(ctx,
"mysql:8.0.36",
mysql.WithConfigFile(filepath.Join("testdata", "my_8.cnf")),
mysql.WithDatabase("foo"),
mysql.WithUsername("root"),
mysql.WithPassword("password"),
mysql.WithScripts(filepath.Join("testdata", "schema.sql")),
)
defer func() {
if err := testcontainers.TerminateContainer(mysqlContainer); err != nil {
log.Printf("failed to terminate container: %s", err)
}
}()
if err != nil {
log.Printf("failed to start container: %s", err)
return
}
}
以下是mini实现支持默认值参数:
package main
import (
"fmt"
"log"
"strings"
)
// 默认值
const (
rootUser = "root"
defaultUser = "test"
defaultPassword = "test"
defaultDatabaseName = "test"
)
// defaultImage {
const defaultImage = "mysql:8.0.36"
// MySQLContainer represents the MySQL container type used in the module
type MySQLContainer struct {
//Container
username string
password string
database string
}
func WithDefaultCredentials() CustomizeRequestOption {
return func(req *GenericContainerRequest) error {
username := req.Env["MYSQL_USER"]
password := req.Env["MYSQL_PASSWORD"]
if strings.EqualFold(rootUser, username) {
delete(req.Env, "MYSQL_USER")
}
if len(password) != 0 && password != "" {
req.Env["MYSQL_ROOT_PASSWORD"] = password
} else if strings.EqualFold(rootUser, username) {
req.Env["MYSQL_ALLOW_EMPTY_PASSWORD"] = "yes"
delete(req.Env, "MYSQL_PASSWORD")
}
return nil
}
}
// ContainerRequest represents the parameters used to get a running container
type ContainerRequest struct {
HostAccessPorts []int
Image string
Entrypoint []string
Env map[string]string
ExposedPorts []string // allow specifying protocol info
Cmd []string
Labels map[string]string
Tmpfs map[string]string
RegistryCred string // Deprecated: Testcontainers will detect registry credentials automatically
Name string // for specifying container name
Hostname string
WorkingDir string // specify the working directory of the container
ExtraHosts []string // Deprecated: Use HostConfigModifier instead
Privileged bool // For starting privileged container
Networks []string // for specifying network names
NetworkAliases map[string][]string // for specifying network aliases
User string // for specifying uid:gid
SkipReaper bool // Deprecated: The reaper is globally controlled by the .testcontainers.properties file or the TESTCONTAINERS_RYUK_DISABLED environment variable
ReaperImage string // Deprecated: use WithImageName ContainerOption instead. Alternative reaper image
AutoRemove bool // Deprecated: Use HostConfigModifier instead. If set to true, the container will be removed from the host when stopped
AlwaysPullImage bool // Always pull image
ImagePlatform string // ImagePlatform describes the platform which the image runs on.
Binds []string // Deprecated: Use HostConfigModifier instead
ShmSize int64 // Amount of memory shared with the host (in bytes)
CapAdd []string // Deprecated: Use HostConfigModifier instead. Add Linux capabilities
CapDrop []string // Deprecated: Use HostConfigModifier instead. Drop Linux capabilities
}
// GenericContainerRequest represents parameters to a generic container
type GenericContainerRequest struct {
ContainerRequest // embedded request for provider
Started bool // whether to auto-start the container
Reuse bool // reuse an existing container if it exists or create a new one. a container name mustn't be empty
}
// ContainerCustomizer is an interface that can be used to configure the Testcontainers container
// request. The passed request will be merged with the default one.
type ContainerCustomizer interface {
Customize(req *GenericContainerRequest) error
}
// CustomizeRequestOption is a type that can be used to configure the Testcontainers container request.
// The passed request will be merged with the default one.
type CustomizeRequestOption func(req *GenericContainerRequest) error
func (opt CustomizeRequestOption) Customize(req *GenericContainerRequest) error {
return opt(req)
}
// RunContainer creates an instance of the MySQL container type
func RunContainer(opts ...ContainerCustomizer) (*MySQLContainer, error) {
// 在实例化定义默认值
// =====================================================
req := ContainerRequest{
Image: defaultImage,
ExposedPorts: []string{"3306/tcp", "33060/tcp"},
Env: map[string]string{
"MYSQL_USER": defaultUser,
"MYSQL_PASSWORD": defaultPassword,
"MYSQL_DATABASE": defaultDatabaseName,
},
}
genericContainerReq := GenericContainerRequest{
ContainerRequest: req,
Started: true,
}
opts = append(opts, WithDefaultCredentials())
// 覆盖默认值
// =================================================
for _, opt := range opts {
if err := opt.Customize(&genericContainerReq); err != nil {
return nil, err
}
}
username, ok := req.Env["MYSQL_USER"]
if !ok {
username = rootUser
}
password := req.Env["MYSQL_PASSWORD"]
if len(password) == 0 && password == "" && !strings.EqualFold(rootUser, username) {
return nil, fmt.Errorf("empty password can be used only with the root user")
}
database := req.Env["MYSQL_DATABASE"]
return &MySQLContainer{username, password, database}, nil
}
func TerminateContainer(c *MySQLContainer) error {
return nil
}
// 处理选项数据
// =======================================
func WithDatabase(database string) CustomizeRequestOption {
return func(req *GenericContainerRequest) error {
req.Env["MYSQL_DATABASE"] = database
return nil
}
}
func WithUsername(username string) CustomizeRequestOption {
return func(req *GenericContainerRequest) error {
req.Env["MYSQL_USER"] = username
return nil
}
}
func WithPassword(password string) CustomizeRequestOption {
return func(req *GenericContainerRequest) error {
req.Env["MYSQL_PASSWORD"] = password
return nil
}
}
// main
// ======================================
func main() {
mysqlContainer, err := RunContainer(
WithDatabase("foo"),
WithUsername("root"),
WithPassword("password"),
)
defer func() {
if err := TerminateContainer(mysqlContainer); err != nil {
log.Printf("failed to terminate container: %s", err)
}
}()
if err != nil {
log.Printf("failed to start container: %s", err)
return
}
}
类/结构体
class Phone:
IMEI = None # 序列号
producer = "ITCASE" # 厂商
def __str__(self):
return f"Phone类对象, name:{self.name}, age: {self.age}"
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
def __eq__(self, other):
return self.age == other.age
# 提供私有成员变量
__is_5g_enable = False # 5g状态
# 提供私有成员方法
def __check_5g(self):
if self.__is_5g_enable:
print("5g开启")
else:
print("5g关闭, 使用4g网络")
def call_by_5g(self):
"""成员方法"""
print("使用5g网络进行通话")
# 定义子类, 复写父类成员
class MyPhone(Phone):
producer = "ITHEIMA" # 复写父类的成员属性
def call_by_5g(self):
print("开启CPU单核模式, 确保通话的时候省电")
# 方式1
# print(f"父类的厂商是: {Phone.producer}")
# Phone.call_by_5g(self)
# 方式2
print(f"父类的厂商是: {super().producer}")
super().call_by_5g()
print("关闭CPU单核模式, 确保性能")
phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
# 在子类中, 调用父类成员
package main
import "fmt"
// Teacher 结构体是值类型。因此,如果要修改值,需要赋值指针地址。
// 同类型的成员属性可以写在一行
type Teacher struct {
name string
age int8
sex byte
}
// NewTeacher 方式一
func NewTeacher() *Teacher {
return &Teacher{
name: "张三",
age: 30,
sex: 1,
}
}
// NewDavid 方式二
func NewDavid() *Teacher {
t := new(Teacher)
//(*t).name = "David"
//(*t).age = 30
//(*t).sex = 1
// 等价于
t.name = "David"
t.age = 30
t.sex = 1
return t
}
// User 演示匿名字段
// 如果字段没有名字,那么默认使用类型作为字段名,同一个类型只能有一个匿名字段。结构体嵌套中采用匿名结构体字段可以模拟继承关系。
type User struct {
string
byte
int8
float64
}
func NewUser() User {
return User{"Steven", 'm', 35, 177.5}
}
type Address struct {
province, city string
}
type Person struct {
name string
age int
address *Address
}
// Sleep 方法
// 接受者p在func关键字和方法名之间编写,接受者可以是struct类型或非struct类型,可以是指针类型或非指针类型。接受者中的变量 在命名时,官方建议使用接受者类型的第一个小写字母。
// 若方法的接受者不是指针,实际只是获取了一个拷贝,而不能真正改变接受者中原来的数据。
func (p Person) Sleep() {
fmt.Println("睡觉")
}
type Student struct {
Person
schoolName string
}
// NewPerson 演示结构体嵌套
// 结构体嵌套可以模拟面向对象编程中的以下两种关系。
// - 聚合关系:一个类作为另一个类的属性。
// - 继承关系:一个类作为另一个类的字类。子类和父类的关系。
func NewPerson() *Person {
return &Person{
name: "Steven",
age: 35,
address: &Address{
province: "北京市",
city: "朝阳区",
},
}
}
// NewStudent 模拟继承关系
func NewStudent() *Student {
return &Student{
Person: *NewPerson(),
schoolName: "清华大学",
}
}
func main() {
// 实例化
t := NewTeacher()
fmt.Println(t)
david := NewDavid()
fmt.Println(david)
// 匿名结构体
addr := struct {
province, city string
}{"山西省", "西安市"}
fmt.Println(addr)
// 匿名字段
user := NewUser()
//如果想依次输出姓名、年龄、身高、性别
fmt.Printf("姓名:%s \n", user.string)
fmt.Printf("身高:%.2f \n", user.float64)
fmt.Printf("性别:%c \n", user.byte)
fmt.Printf("年龄:%d \n", user.int8)
person := NewPerson()
fmt.Println(person)
student := NewStudent()
fmt.Println(student)
}
class Person {
// 构造器
constructor(public name: string,
public age: number) {
this.name = name
this.age = age
}
// 方法
speak() {
console.log(`我叫: ${this.name}, 今年${this.age}岁`)
}
}
// Person实例
const p1 = new Person('周杰伦', 38)
// 继承Person
class Student extends Person {
grade: string
// 构造器
constructor(name: string, age: number, grade: string) {
super(name, age);
this.grade = grade
}
// 重写父类继承的方法
override speak() {
console.log(`我是学生, 我叫: ${this.name}, 今年${this.age}岁, 在读${this.grade}年级`)
}
// 子类自己的方法
study() {
console.log(`${this.name}正在努力学习中......`)
}
}
抽象类
- abstract class Package {
constructor(public weight: number) {} // 抽象方法 abstract calculate(): number // 具体方法 printPackage(){
console.log(包裹重量为: ${this.weight})
}
}
- class StandardPackage extends Package{
- constructor(
weight: number, public unitPrice: number
- ) {
super(weight);
} calculate(): number {
return this.weight * this.unitPrice
}
}
const s1 = new StandardPackage(10, 5) console.log(s1.calculate());
捕获异常
# arr = [10, 20, 30]
arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师']
print(arr)
print(arr[0])
print(len(arr))
# 循环
for item in arr:
print(item)
打断点
<script>
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/debugger
function potentiallyBuggyCode() {
const v = 1
console.log(v)
debugger;
// do potentially buggy stuff to examine, step through, etc.
}
potentiallyBuggyCode()
</script>
接口
// 定义类结构
// ================================================
// PersonInterface接口
interface PersonInterface{
name: string
age: number
speak(n: number): void
}
class Person implements PersonInterface{
constructor(
public name: string,
public age: number,
) {}
speak(n: number) {
console.log(`你好, 我叫${this.name}, 我的年龄是${this.age}`)
}
}
// 定义对象结构
// ==========================================
interface UserInterface{
name: string
readonly gender: string // 只读属性
age?: number // 可选属性
run: (n: number) => void
}
const user: UserInterface ={
name: "张三",
gender: "男",
age: 18,
run(n){
console.log(`奔跑了${n}米`)
}
}
// 定义函数结构
// =====================================
interface CountInterface{
(a: number, b: number): number;
}
const count: CountInterface = (x, y) => {
return x + y
}
// 接口之间的继承
// ===========================
interface StudentInterface extends PersonInterface{
grade: string // 年级
}
const stu: StudentInterface = {
name: '张三',
age: 18,
grade: '初二',
speak(n: number) {}
}
泛型
// 泛型函数
// ==============================
function logData<T>(data: T): T{
console.log(data)
return data
}
logData(100)
logData('hello')
// 泛型接口
// =============================
interface PersonInterface<T> {
name: string,
age: number,
extraInfo: T
}
let p1: PersonInterface<string>
let p2: PersonInterface<number>
p1 = { name: '张三', age: 18, extraInfo: '一个好人'}
p2 = { name: '张三', age: 18, extraInfo: 250}
// 泛型类
// ===============================
class Person<T> {
constructor(
public name: string,
public age: number,
public extraInfo: T
) {}
speak(){
console.log(`我叫${this.name}今年${this.age}岁了`)
console.log(this.extraInfo)
}
}
const p3 = new Person<number>("tom", 30, 250);