1、语言类型
Python | Golang |
---|---|
Python 是一种解释型语言(开发过程中不需要编译) | Golang是静态类型语言(在程序运行前检查类型) |
Python 是交互式语言(可以在Python提示符 >>> 后直接执行代码) | Golang核心思想是提高编程效率 |
Python 是面向对象语言(代码封装在对象里) |
2、下载地址
Python | Golang |
---|---|
https://www.python.org/ | https://golang.org/dl/ |
3、环境变量
环境 | Python | Golang |
---|---|---|
路径 | PATH=$PATH:/usr/local/bin/python | PATH=$PATH:/usr/local/go/bin |
编译 | 无 | go Module、go Vendor、go glide |
编译后文件格式 | 无 | src:存放源码 pkg:存放编译后生成的文件 bin:存放编译后生成的可执行文件 |
linux环境里可用which python和which go来查看路径
4、程序运行
Python | Golang |
---|---|
python test.py | go run test.go |
5、语法结构
结构 | Python | Golang |
---|---|---|
包声明 | 无 | package xxx |
引入包 | from xxx import yyy | import xxx/yyy |
类 | 具有相同的属性和方法的对象的集合 | 不支持 |
类方法 | 类的方法与普通的函数只有一个特别的区别是它们必须有一个额外的参数名称,按照惯例是self,self代表类的实例,而非类 | 不支持 |
构造方法 | 创建对象的时候第一个被自动调用的函数,系统默认提供了一个无参的构造函数,作用是给对象的成员变量赋值函数名固定是__ init__,只能被调用一次(见python-1) | 无 |
私有变量 | __name 函数前加__不能被对象直接调用 |
无 |
私有方法 | def __get_name() 函数前加__不能在类之外被访问 |
func getName() 函数首字母小写不能被其他包访问 |
继承 | 把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;class 子类(父类1、父类2) (见python-2) | 无 |
多态 | 同一种事务的多种形态就是多态 | 无 |
结构体 | 无 | type xxx struct{} |
运算符重载 | def __str__(self):xxx 可在需要字符串输出时直接使用如print() | func (x 结构体) String() string {}需要被调用才可以使用,如结构体对象.String() |
全局变量 | 在函数外定义 | 在包里定义 |
局部变量 | 在函数内定义,若想在函数内修改全局变量要加global(见python-4) | 在函数内定义 |
- python-1
# 系统默认提供
def __ init__(self):
pass
# 自定义构造函数系统将不再提供无参的构造函数
def __init__(self,*s): #设置不定长参数
pass
- python-2
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #强制调用父类已被覆盖的方法
- python-3
type Book struct{
author string
age int
}
结构体 | Golang |
---|---|
声明 | var book Book |
赋值 | book.age = 33 |
获取 | book.age |
- python-4
num = 1
def fun1():
global num # 需要使用 global 关键字声明
num = 123
print(num)
fun1() #123
print(num) #123
6、基础语法
对比项 | Python | Golang |
---|---|---|
标识符 | 第一个字符必须是字母或下划线 _,其他的部分由字母、数字和下划线组成 | 第一个字符必须是字母或下划线 _,其他的部分由字母、数字和下划线组成 |
注释 | # | // |
打印 | print() 默认换行 | fmt.Println() |
格式化打印 | (“My name is %s” % “amber”) | (“My name is %s”, “amber”) |
变量声明 | 无 | var name string var age int = 10 |
赋值 | a = 100 | a := 100 |
多变量赋值 | a = b = c = 1 | a,b,c = 1, 1, 1 |
多类型赋值 | a, b = 1, “amb” | a, b := 1, “amb” |
类型判断 | str = "aaa" type(str)=string |
str := "aaa" str.(type)=string |
常量 | 无 | const Pi = 3.1415 |
7、数学函数
math | Python | Golang |
---|---|---|
max | 参数要么全是(int、float、complex、bool)要么全是序列 max(1, 3.2, 5) 、max([1,2], [3,4]) | 参数必须是float64类型 math.Max(-1.3, 0) |
pow | 参数是整形 pow(100, 2)=10000 | 参数是float64类型 math.Pow(100, 2) |
round | 参数是float和保留的小数位数round(23.19, 1)=23.2 | math.Round(4.2)=4 |
8、随机数
随机数 | Python | Golang |
---|---|---|
导入 | import random | import “math/rand” |
序列随机数 | random.choice([1, 2, 3, 5, 9])=3 random.choice(‘Runoob’)=o random.choice(range(10)),范围[0,10) |
不支持 |
种子 | random.seed(10) | rand.Seed(10) |
随机数 | random.random(),范围[0,1) random.randint(0,10)=4 |
rand.Intn(10),范围[0,10) |
9、字符串
str = “abcd”
sjoin = “-”
string | Python | Golang |
---|---|---|
切分 | str[:1]=‘a’ | str[:1]=‘a’ |
字符串拼接 | “abc”+“xyz” | “abc”+“xyz” |
重复输出 | str*2=“abcdabcd” | strings.Repeat(str, 2)=“abcdabcd” |
包含 | if ‘a’ in str: | strings.Contains(str, “a”)=true |
首字母大写 | str.capitalize()=“Abcd” | 不支持 |
元素出现次数 | str.count(‘ab’)=1 str.count(‘ab’, 0, 10)指定下标范围 |
strings.Count(str, ‘ab’)=1 |
是否以元素结尾 | str.endswith(‘d’)=true str.endswith(d,0,1)=false |
不支持 |
找到元素下标 | str.find(‘bc’)=1 str.find(‘a’,3)=-1从下标3开始找 str.find(‘ff’,0, 3)=-1 |
不支持 |
找到索引 | str.index(‘bc’)=1 str.index(‘a’,3)=异常,从下标3开始找 str.index(‘ff’,0, 3)=异常 |
strings.Index(str, “aa”)=-1 |
是否全是数字 | str.isdigit()=false | 不支持 |
字符连接 | sjoin.join(str)=“a-b-c-d” | strings.Join(str,"-")=“a-b-c-d” |
小写转换 | str.lower()=“abcd” | strings.ToLower(str)=“abcd” |
大写转换 | str.upper()=“ABCD” | strings.ToUpper(str)=“ABCD” |
替换 | str.replace(“ab”,“AB”)=“ABcd” | strings.Replace(str, “ab”, “AB”, -1)=“ABcd”,-1表示全部替换, 0表示不替换, 1表示替换第一个, 2表示替换第二个… |
修剪掉两端的字符 | str.strip(’ ') | strings.Trim(" Achtung! Achtung ", " ")=“Achtung! Achtung” |
修改 | str[2] = ‘m’ | b := []byte(str) b[2] = 'm’ str := string(b) |
是否以指定字符开头 | 不支持 | strings.HasPrefix(“http://127.0.0.1”, “https”)=false |
10、数组
list | Python | Golang |
---|---|---|
定义 | 一组元素集合 | 具有相同类型的元素集合,长度固定 |
引用类型 | 地址传递 list.copy()值传递 |
值传递 |
元素类型 | 可以不一致list=[‘q’, 23, [3,4]] | 必须一致list:=[1, 2] |
初始化 | list=[‘a’,‘b’,‘c’] | list := byte[]{‘a’,‘b’,‘c’} |
尾部索引 | list[-1] | 不支持 |
添加元素 | list = list.append(‘f’) | list = append(list, ‘f’) |
元素插入指定位置 | list = list.insert(1, ‘m’) | 不支持 |
两数组合并 | l1.extend(l2) l3 = l1+l2 |
l1 = append(l1, l2…) |
更新列表 | list[1] = ‘m’ | list[1] = ‘m’ |
删除元素 | del list[1] | list = list[:1] |
统计个数 | len(list) | len(list) |
字符串转数组 | str = "abc" nlist = list(str) |
str := "abc" nlist := []byte(str) |
最大元素 | max(list)=‘c’ | 不支持 |
统计元素出现次数 | list.count(‘c’)=1 | 不支持 |
移除列表元素 | list.pop()=‘c’ 默认移除最后一个元素 list.pop(1)='b’移除下标为1的元素 |
不支持 |
删除指定元素 | list.remove(‘c’) | 不支持 |
列表反转 | list.reverse() | 不支持 |
排序 | list.sort() 正序 list.sort(reverse=True) 逆序 |
sort.Ints(list) sort.Strings(list) |
清空列表 | list.clear() | 不支持 |
11、元祖(Python独有)
元祖 | Python |
---|---|
元素类型 | 可以不一致 |
初始化 | tup = (1,2,‘b’) |
元素增加 | 不支持 |
元素修改 | 不支持 |
元素删除 | 不支持 |
删除元祖 | del tup |
12、字典(Python独有)
字典 | Python |
---|---|
元素类型 | 键必须是唯一,类型不可变,值不做要求 |
初始化 | dic = {“a”: 1, “b”: “mm”, “c”: 44} |
元素获取 | dic[“a”]=1 dic[“m”] 报错 |
元素修改 | dic[“a”] = 3 |
元素删除 | del dic[“a”] |
统计长度 | len(dic) |
转为string类型 | str(dic) |
判断key是否在字典 | if ‘a’ in dic : |
删除元素 | dic.pop(‘a’) dic.pop(‘v’,‘monkey’)未找到key的值返回’monkey’ |
两字典合并 | dic2 = {‘d’: 0} dic.update(dic2)={“a”: 1, “b”: “mm”, “c”: 44, ‘d’: 0} |
13、集合(Python独有)
集合 | Python |
---|---|
元素类型 | 无序,不重复,类型可以不一致 |
初始化 | s = {“a”, “b”, “c”, 3} |
添加元素 | s.add(‘d’) |
添加序列 | s.update([1,2]) |
删除元素 | s.remove(‘m’)若元素不存在报错 s.discard(‘m’)不报错 |
随机删除元素 | s.pop()=“b” |
集合运算- | s1 = {1,3,4} s2={1,5,6} s1-s2={3,4} 集合s1中包含而集合s2中不包含的元素 |
集合运算 | | s1|s2={1,3,4,5,6} 集合s1和s2中的所有元素 |
集合运算 ^ | s1 ^ s2={3,4,5,6} 除去s1和s2公共元素 |
集合运算 & | s1 & s2={1} s1和s2公共元素 |
14、切片(Golang独有)
切片 | Golang |
---|---|
定义 | 无序的键值对的集合 |
元素类型 | 类型必须一致 |
初始化 | s = []string{“a”, “b”, “c”} var s []string = make([]string, 4, 5) |
长度 | len(s) |
容量 | cap(s) 容量>=长度 |
增加元素 | append(s, “m”) |
15、map集合(Golang独有)
map | Golang |
---|---|
定义 | 具有相同类型的元素集合,长度可变 |
初始化 | hmap := make(map[int]string) 不用make初始化的话就是nil,里面无法存放健值对 |
插入元素 | hmap[1] = “hello” |
删除元素 | delete(hmap, 1) |
查询元素 | hmap[1] |
16、条件语句
条件 | Python | Golang |
---|---|---|
if | if true : | if true {} |
for | for i in list : | for i := range list {} |
while | while true : | 不支持 |
select | 不支持 | select{case xxx:} 随机执行一个可运行的case,如果没有case可运行,它将阻塞,直到有case可运行 |
switch | 不支持 | switch xxx {case xxx:} |
17、异常
Python | Golang |
---|---|
try:执行 try 子句(在关键字 try 和关键字 except 之间的语句) | defer:程序运行到defer暂停将defer后的语句压入独立栈,当程序执行完,从defer栈中按先入后出的形式执行出栈 |
except:执行 try 子句的过程中发生了异常,except 子句将被执行 | recover:捕获异常 |
finally:必须要执行的语句 | panic:程序执行过程中的异常,常见的为空指针异常 |
18、正则匹配
Python | Golang |
---|---|
import re match = re.findall(r’[a-z]’, ‘aaa’)#返回的是匹配成功的字符串aaa |
import “regexp" match,err:=regexp.MatchString(”[a-z]",“aaa”)//返回的第一个参数是bool类型即匹配结果,第二个参数是error类型 |
19、迭代器与生成器(Python独有)
迭代器 | Python |
---|---|
定义 | 内部实现iter() 和 next()方法,iter()方法返回迭代器对象本身;next()方法返回容器的下一个元素,在结尾时引发StopIteration异常 |
举例 | list=[1,2,3,4] it = iter(list) #创建迭代器对象 print (next(it)) |
for循环实现 | for i in it : print(i) 凡可用for循环遍历的对象内部必然有iter(), for语句就会自动的通过iter()方法来获得迭代器对象,并且通过next()方法来获取下一个元素 |
生成器 | Python |
---|---|
定义 | 使用了 yield 的函数被称为生成器 调用一个生成器函数,返回的是一个迭代器对象 |
yield作用 | 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行,类似断点 |
20、函数
函数 | Python | Golang |
---|---|---|
关键字 | def xxx() : | 方法 func xxx() { |
默认参数 | def xxx(name=‘amb’, age=15) | 不支持 |
返回值定义 | 函数返回值无需提前定义 | 返回值类型要先定义 |
多个返回值 | 不支持 | 支持 |
值传递/址传递 | 根据参数类型而定 | 值传递 |
不定长参数 | def xxx(arg, *tup)一个*代表传入的参数是元祖类型,个数不定 def xxx(arg, **dic)两个*代表传入的参数是字典类型,个数不定 |
不支持 |
匿名函数 | sum = lambda arg1, arg2: arg1 + arg2 print(sun(1, 2)) |
第一种:定义时并调用 res := func (n1,n2 int) int { return n1 + n2}(10, 30) 第二种:将函数赋给函数变量再调用 res := func (n1,n2 int) int { return n1 + n2} print(res(10,20)) |
主函数 | if __name__ == ‘__main__’: | func main(){} |
内置函数 | dir(sys)列出模块内定义的所有名称 dir()列出当前定义的所有名称 |
不支持 |
格式打印 | print(’{0}网址{1}’.format(‘小猫’,‘www.xxx.com’)) | fmt.Printf(“xxx”) |
21、数据结构
数据结构 | Python | Golang |
---|---|---|
for遍历list | for key,value in enumerate(list) | for key,value := range list |
for遍历dict | for key,value in dict.items() | - |
数组做队列 | 入队:list.append() 出队:queue = deque([“Eric”, “John”]) queue.popleft()/list.pop(0)时间复杂度O(n) |
入队:list = append(list, “amb”) 出队:list[1:] |
数组做栈 | 入栈:list.append() 出栈:list.pop() |
入栈:list = append(list, “amb”) 出栈:list[:len(list)-1] |
表推导式 | vec = [2, 4, 6] [3*x for x in vec]=[6, 12, 18] |
- |
del使用 | del[:3] | - |
集合 | a = set(‘abracadabra’) a={‘a’, ‘r’, ‘b’, ‘c’, ‘d’} |
- |
字典 | sorted(dict.keys()) sorted(dict.values()) |
- |
字典推导式 | {x: x*2 for x in (2, 4, 6)}={2:4, 4:8, 6:12} | - |
zip遍历多个序列 | questions = [‘name’, ‘age’] answers = [‘amber’, 20] for k, v in zip(questions, answers): |
- |
22、交互模块
系统模块 | Python | Golang |
---|---|---|
获取传入参数 | import sys for i in sys.argv:xxx $ python test.py 参数1 参数2 |
- |
读取键盘输入 | str = input(“请输入:”) print ("你输入的内容是: ", str) |
import “bufio” import "os" reader := bufio.NewReader(os.Stdin) result, err := reader.ReadString(’\n’) |
srt() | 调用了对象的 __str__方法来输出结果,便于理解 | - |
repr() | 调用对象的__repr__方法来输出结果,除了对象内容,还需要展示出对象的数据类型信息,适合开发和调试阶段使用 | - |
23、文件操作
文件 | Python | Golang |
---|---|---|
判断文件是否存在 | os.payh.exists(“filename”) | os.Stat(“filename”) |
打开文件 | f = open(“filename”, “w”) | f,err := os.OpenFile(“filename”, os.O_APPEND, 0666) |
读取内容 | f.read(size)size是可选的数字参数,不指定默认读取全部 | n,err := ioutil.ReadFile(f) |
逐行读取 | str = f.readline() | reader := bufio.NewReader(f) str, err := reader.ReadString(’\n’) |
写入内容 | f.write(“xxx”) | n,err := io.WriteString(f, “xxx”) n是写入的字节数 |
关闭文件 | f.close() | f.Close() |
24、序列化和反序列化
对比项 | Python | Golang |
---|---|---|
引入模块 | import json | import “encoding/json” |
序列化 | data = {‘name’:“amb”,} json_str = json.dumps(data) #Python字典类型转换为JSON对象 |
json_str,err = json.Marshal(&stu) #结将构体序列化为JSON对象 |
反序列化 | ndata = json.loads(json_str) # 将JSON对象转换为Python字典 |
json.Unmarshal(json_str,&stu) #将JSON对象反序列化到stu结构体 |
JSON数据写入文件 | with open(‘data.json’, ‘w’) as f: json.dump(data, f) |
无 |
读取数据文件 | with open(‘data.json’, ‘r’) as f: data = json.load(f) |
无 |
pickle |
---|
import pickle |
data = [‘aa’, ‘bb’] str = pickle.dumps(data) #dumps将数据序列化为只有python语言认识的字符串 |
res = pickle.loads(str) # loads将pickle数据反序列化为python的数据结构 |
with open(‘tmp.pk’, ‘w’) as f: pickle.dump(data, f)dump #将数据序列化为只有python语言认识的字符串,并写入文件 |
with open(‘tmp.pk’, ‘r’) as f: data = pickle.load(f) #load从数据文件中读取数据,并转换为python的数据结构 |
25、进程、线程、协程
并发和并行 |
---|
并发:多线程程序在单核上运行,多个任务作用在一个cpu,某一时间点上只有一个任务在执行 |
并行:多线程程序在多核上运行,多个任务作用在多个cpi,某一时间点上有多个任务在执行 |
对比项 | Python | Golang |
---|---|---|
进程 | 进程池内部维护一个进程序列,每次去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序等待,直到进程池中有可用进程为止(见python-1) | — |
线程 | 线程是操作系统能够进行运算调度的最小单位(见python-2) | — |
协程 | 协程是轻量级线程。协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态,没有线程切换的开销,不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突(见python-3) | 程序遇到go关键字时,主线程会再开出一个分支执行go后面的方法,实现并发主线程仍继续执行,若主线程执行完毕,分支线程无论是否结束都要结束(见golang-3协程通信) |
- python-1
#1、apply(同步),等待函数执行完毕后释放进程
#2、apply_async(异步),不需要等待函数执行完毕,只要函数接收就释放进程
from multiprocessing import Process,Pool
import time
def Foo(i):
time.sleep(1)
return i*2
def Bar(arg):
print('current number::',arg)
if __name__ == "__main__":
pool = Pool(3)#定义一个进程池,里面有3个进程
for i in range(10):
#callback是回调函数,就是在执行完Foo方法后会自动执行Bar函数,并且自动把Foo函数的返回值作为参数传入Bar函数
pool.apply_async(func=Foo, args=(i,),callback=Bar)
#pool.apply(func=Foo, args=(i,))
pool.close()#关闭进程池
pool.join()#进程池中进程执行完毕后再关闭,(必须先close在join)
- python-2
import threading
import time
def hello(name):
print("Hello %s"%name)
time.sleep(3)
def hi(name):
print("Hello %s"%name)
time.sleep(3)
if __name__ == "__main__":
t1=threading.Thread(target=hello,args=("amber",)) #生成线程实例
t2=threading.Thread(target=hi,args=("paige",))
t1.setName("aaa") #设置线程名
t1.setDaemon(True) #设置为守护线程,当主线程结束后,t1线程也随之终止,要在start前设置
t1.start() #启动线程
t2.start()
t2.join() #join主线程阻塞等待t2先执行完
print(t1.getName()) #获取线程名
- python-3
import gevent
import time
def one():
print('11')
time.sleep(3)
print('22')
def two():
print('33')
print('44')
gevent.joinall([
gevent.spawn(one),
gevent.spawn(two),
])
#输出结果,并发执行
11
33
44
22
- golang-3
在Go中有一种特殊的类型channle通道,可以通过它来进行goroutine之间的通信,channel的通信保证了同步性。同一时间只有一个协程可以访问数据,所以不会出现数据竞争
//无缓冲
//需要发送方和接收方同时准备好,不然发送方会一直阻塞,直到数据被接收方处理;接收方阻塞直到数据进来,不会保存数据
buffer := make(chan string)
buffer2 := make(chan string, 0)
//带缓冲
//如果缓冲区已满,发送方的主进程或者协程会被阻塞,发送方只能在接收方取走数据后才能从阻塞状态恢复;如果为空,接收方的协程会被阻塞
buffer3 := make(chan string, 4)
//select监听channel
//如果有多个channel接收数据,select会随机选择一个case来处理,没有case需要处理,select会阻塞,可配合超时时间一并处理
package main
import (
"fmt"
"time"
)
func main() {
buffer := make(chan string, 1)
go func() {
time.Sleep(time.Second * 3)
chan1 <- "res"
}()
select {
case res := <-chan1: //3秒之后才会有数据进入槽chan1
fmt.Println(res)
case <-time.After(time.Second * 1)://定义超时情况,1秒后超时.这个超时时间比上面的case短,所以先运行这个case
fmt.Println("timeout 1 second")
}
}
// channel关闭
//close()掉了,你继续往里面写数据,会出现panic
buf := make(chan int, 10)
close(buf)
buf <- "res" //panic
//channel状态
buf := make(chan int, 10)
buf <- "res"
close(buf)
i, ok := <-buf
fmt.Printf("%d, %t", i, ok) //0, false
26、OS模块
对比项 | Python | Golang |
---|---|---|
获取环境变量 | os.getenv() | os.Getenv(“GOPATH”) |
切换目录 | os.chdir() | os.Chdir() |
获取当前路径 | os.getcwd() | os.Getwd() |
27、连接mysql
Mysql | Python | Golang |
---|---|---|
倒入包 | import pymysql | import “github.com/jinzhu/gorm” |
打开数据库连接 | db = pymysql.connect(“127.0.0.1:3306”,“amber”,“123”,“数据库名” ) | DB, err := gorm.Open(“mysql”, “amber:123@tcp(127.0.0.1:3306)/数据库名?charset=utf8”) |
创建游标 | cursor = db.cursor() | 无 |
执行sql | cursor.execute(“insert xxx into xxx”) | DB.Raw(“insert xxx into xxx”) |
关闭连接 | db.close() | DB.Close() |
28、网络编程
套接字 | 应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯 |
---|
对比 | Python |
---|---|
倒入包 | from socket import * |
创建套接字 | tcps = socket(AF_INET, SOCK_STREAM) |
把地址绑定到套接字 | tcps.bind((“192.15.2.1”,3340)) |
监听链接 | tcps.listen(100) |
接受客户端链接 | conn, addr = tcps.accept() |
对话接收 | tcpc.recv(1024) |
对话发送 | tcpc.send(msg) |
关闭客户端套接字 | tcpc.close() |
关闭服务器套接字 | tcps.close() |
- python服务端
from socket import *
import time
COD = 'utf-8'
HOST = '192.168.1.1' # 主机ip
PORT = 8080 # 软件端口号
BUFSIZ = 1024
ADDR = (HOST, PORT)
SIZE = 10
tcpS = socket(AF_INET, SOCK_STREAM) # 创建socket对象
tcpS.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #加入socket配置,重用ip和端口
tcpS.bind(ADDR) # 绑定ip端口号
tcpS.listen(SIZE) # 设置最大链接数
while True:
print("服务器启动,监听客户端链接")
conn, addr = tcpS.accept()
print("链接的客户端", addr)
while True:
try:
data = conn.recv(BUFSIZ) # 读取已链接客户的发送的消息
except Exception:
print("断开的客户端", addr)
break
print("客户端发送的内容:",data.decode(COD))
if not data:
break
msg = time.strftime("%Y-%m-%d %X") #获取结构化事件戳
msg1 = '[%s]:%s' % (msg, data.decode(COD))
conn.send(msg1.encode(COD)) #发送消息给已链接客户端
conn.close() #关闭客户端链接
tcpS.closel()
- python客户端
from socket import *
HOST = '192.168.1.1' #服务端ip
PORT = 8080 #服务端端口号
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM) #创建socket对象
tcpCliSock.connect(ADDR) #连接服务器
while True:
data = input('>>').strip()
if not data:
break
tcpCliSock.send(data.encode('utf-8')) #发送消息
data = tcpCliSock.recv(BUFSIZ) #读取消息
if not data:
break
print(data.decode('utf-8'))
tcpCliSock.close() #关闭客户端
- golang服务端
func main() {
listen, err := net.Listen("tcp","127.0.0.1:2000") //监听2000端口
if err != nil {
fmt.Println("listen failed, err:", err)
return
}
for {
conn, err := listen.Accept() // 建立连接
if err != nil {
fmt.Println("accept failed, err:", err)
continue
}
go process(conn) // 启动一个goroutine处理连接
}
}
// 读取数据
func process(conn net.Conn) {
defer conn.Close() // 关闭连接
for {
reader := bufio.NewReader(conn)
var buf [128]byte
n, err := reader.Read(buf[:]) // 读取conn链接中数据
if err != nil {
fmt.Println("read from client failed, err:", err)
break
}
recvStr := string(buf[:n])
fmt.Println("收到client端发来的数据:", recvStr)
conn.Write([]byte(recvStr)) // 发送数据
}
}
- golang客户端
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:2000") //连接服务端2000端口
if err != nil {
fmt.Println("err :", err)
return
}
defer conn.Close() // 关闭连接
inputReader := bufio.NewReader(os.Stdin)
for {
input, _ := inputReader.ReadString('\n') // 读取用户输入
inputInfo := strings.Trim(input, "\r\n")
if strings.ToUpper(inputInfo) == "QUIT" { // 如果输入q就退出
return
}
_, err = conn.Write([]byte(inputInfo)) // 发送数据
if err != nil {
return
}
buf := [512]byte{}
n, err := conn.Read(buf[:])
if err != nil {
fmt.Println("recv failed, err:", err)
return
}
fmt.Println(string(buf[:n]))
}
}
29、时间和日期
对比 | Python | Golang |
---|---|---|
倒入 | import time | import “time” |
当前时间 | time.time() #1615096801.099059 |
time.Now() //2021-03-07 14:08:18.910348 +0800 CST m=+0.000240927 |
格式化时间 | time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # ‘2021-03-07 14:03:13’ |
time.Now().Format(“2006-01-02 15:04:05”) |
间隔时间 | t1 := time.time() t2 := time.time() t2 - t1 |
synTime := time.Now() time.Since(synTime) |
30、总结
总结 | Golang |
---|---|
值类型 | int系列,float系列,bool,string,数组,struct |
引用类型 | 指针,slice切片,map,管道,interface |
new | a := 100 a指向一块内存空间,空间里面存放100 b := new(int) *b = 100在内存中开辟一块空间,里面存放存放100的地址 |
make | 对于map、channel、slice等引用数据类型需要make分配内存才可以初始化,才可以赋值,内存里存放的事对应的数据 |
注意 | golang中 “{” 不可以单独放在一行 |
总结 | Python |
---|---|
值传递 | int,float,str,boolean,tuple |
引用传递 | list,dict,set |
转载:https://blog.csdn.net/ambzheng/article/details/114484837
查看评论