原创大约 22 分钟
虽然前面已经介绍了大量的聚合函数,但还是有一些高频出现的没覆盖到,所以这里就来集中汇总一下。
1. topK(N)(x)
经常会出现统计数量,然后按数量的倒序排序并取前N个值的场景,这就是典型的TopN
需求。
Clickhouse直接提供了返回指定列中最频繁出现的前N个值的函数。
原创大约 6 分钟
Clickhouse一共指定了二十多个函数为高阶函数,它们中的大部分都在高阶函数中列出。
由于文档更新原因,有些函数没列出来,而有些函数的文档有错误,这里全部都一一修正。
原创大约 14 分钟
原创大约 16 分钟
package main
import (
"fmt"
"sync"
)
/*
go中的函数全部都是“值传递”
函数可以返回多个值
1. 函数返回多个值,返回值类型可以不同
2. 函数返回多个值,返回值类型可以相同
3. 函数返回多个值,返回值类型可以相同,但是顺序可以不同
4. 函数返回多个值,返回值类型可以相同,但是顺序可以不同,但是不能省略
*/
func add1(a, b int) int {
a = 3
fmt.Println(a)
return a + b
}
// 因为已经定义了返回值名称,所以return后面可以省略变量名
func add2(a, b int) (sum int, err error) {
sum = a + b
return
}
// 变长参数
func add4(items ...int) (sum int) {
for _, v := range items {
sum += v
}
return
}
func add5(desc string, items ...int) (sum int) {
fmt.Printf("%s: ", desc)
for _, v := range items {
sum += v
}
return
}
// 一个计算器函数
func calc1(desc string, items ...int) func() {
switch desc {
case "sum":
//for _, v := range items {
// sum += v
//}
return func() {
fmt.Println("这是加法")
}
case "sub":
//for i, v := range items {
// if i == 0 {
// sum = v
// } else {
// sum -= v
// }
//}
return func() {
fmt.Println("这是减法")
}
default:
return func() {
fmt.Println("这是默认")
}
}
}
// 参数和返回值都是函数
func calc2(desc string, myfunc func(items ...int) int) func() {
switch desc {
case "+":
fmt.Println(myfunc(1, 2, 3))
return func() {
fmt.Println("加法运算")
}
case "-":
fmt.Println(myfunc(1, 2))
return func() {
fmt.Println("减法运算")
}
default:
fmt.Println(myfunc())
return func() {
fmt.Println("默认运算")
}
}
}
// 闭包函数
func autoIncrement() func() int {
local := 0
// 在一个函数中访问另一个函数的局部变量
return func() int {
local += 1
return local
}
}
func deferReturn() (ret int) {
// defer后面也可以自定义函数
// 在return之前执行
defer func() {
ret++
}()
// 由于在return之前调用,因此ret的值是11
return 10
}
func main() {
// 函数
// go支持普通函数、匿名函数和闭包
/*
go中函数是一等公民
1. 函数本身可以当作变量
2. 函数可以满足接口
3. 匿名函数和闭包
*/
a := 1
b := 2
fmt.Println(add1(a, b))
// 因为a是传值引用,所以本身的值不会受到影响
fmt.Println(a)
fmt.Println("====================")
r1, _ := add2(1, 2)
fmt.Println(r1)
fmt.Println("====================")
// 函数可变参数
fmt.Println(add5("累加求和"))
fmt.Println(add5("累加求和", 1))
fmt.Println(add5("累加求和", 1, 2))
fmt.Println("====================")
// 函数的一等公民特性
// 直接将函数“赋值”给了一个变量,让这个变量也具有了函数的特性
test := add5
// 变量可以像函数那样使用
fmt.Println(test("累加求和"))
fmt.Println("====================")
// 这样是无法显示结果的
calc1("22")
// 因为函数返回的是一个函数,所以需要调用这个函数
calc1("22")()
fmt.Println("====================")
calc2("+", add4)()
// 匿名函数
f := func(items ...int) int {
sum := 0
for _, v := range items {
sum += v
}
return sum
}
fmt.Println(f(1, 2, 3))
fmt.Println("====================")
/*
函数的闭包:在一个(匿名的)内部函数中,引用了它所在的外部函数中的变量,就叫闭包
*/
// 通过返回匿名函数,实现动态的自增逻辑
nextFunc := autoIncrement()
for i := 0; i < 5; i++ {
fmt.Println(nextFunc())
}
// 再次调用则归零重新计算
nextFunc = autoIncrement()
// 函数的defer,相当于java中的finally
var lock sync.Mutex
lock.Lock()
// defer后面的代码一定会在函数的return之前执行
defer lock.Unlock()
// 演示多个defer的执行顺序:离return近的先执行,相当于执行“出栈”操作
defer fmt.Println("defer1")
defer fmt.Println("defer2")
defer fmt.Println("defer3")
fmt.Println("main")
ret := deferReturn()
fmt.Println(ret)
return
}
原创大约 3 分钟
函数
# 默认参数必须定义在非默认参数之后
def login(age, username='admin', password='123456'):
if username == 'admin' and password == '123456':
# 函数返回多个值
return True, '登录成功'
else:
# 函数返回多个值
return False, '登录失败'
# 命名参数
result, msg = login(password='123456', age = 18)
print(result, msg)
# 变长参数
def calc(*args):
print("type(args) ==>", type(args))
sum = 0
for i in args:
sum += i
print(sum)
# 传递可变参数
calc(1, 2, 3, 4, 5)
# 不能直接传递元组参数
a = (1, 2, 3, 4, 5)
# 这样传递会报错
# calc(a)
# 需要传递它的地址
calc(*a)
# 列表也是一样
a = [1, 2, 3, 4, 5]
calc(*a)
# 这里默认参数并没有在非默认参数之后,仍然可以执行
def myfunc1(param0, param1='hello', *param2, param3='python'):
print("param0 ==>", param0)
print("param1 ==>", param1)
print("param2 ==>", param2)
print("param3 ==>", param3)
myfunc1('hello', 'world', 'python', 'java', 'scala', 'go')
# 支持任意数量的命名参数
def myfunc2(**params):
print("params ==>", params)
for key in params:
print("key ==>", key)
print()
for key, value in params.items():
print("key ==>", key, ", value ==>", value)
myfunc2(name='zhangsan', age=18, sex='male')
# 也可以这样调用
a = {'name': 'zhangsan', 'age': 18, 'sex': 'male'}
myfunc2(**a)
# 变量作用域
def myfunc3():
sum = 0
# 局部变量
name = 'zhangsan'
# 块级作用域
for i in range(0, 9):
# 不需要事先声明name变量,可以直接使用
name = 'lixingyun'
sum += i
print("name ==>", name)
print("sum ==>", sum)
myfunc3()
# 全局变量
global_var = 1
def myfunc4():
# 如果没有赋值,打印出来的值是1
global_var = 2
print("global_var ==>", global_var)
def myfunc5():
# 如果没有赋值,打印出来的值不会是3
global_var = 3
print("global_var ==>", global_var)
myfunc5()
# 作用域链
myfunc4()
# 依旧是1
print("global_var ==>", global_var)
# 将局部变量转换为全局变量
def myfunc6():
global local_var
local_var = 10
myfunc6()
print("local_var ==>", local_var)
大约 5 分钟