Cet article est un article du mardi 24 décembre de Calendrier de l'Avent DeNA 2019.
J'utilise généralement Perl principalement, mais je l'ai résumé dans le but d'apprendre Go et de réviser Python. La grammaire de Python est très simple, donc j'ai pensé qu'il serait rapide d'apprendre Go par la différence. J'ai l'intention d'écrire autant que possible, mais je pense qu'il y a plusieurs pénuries. Notez s'il vous plaît.
Tout d'abord, comment rédiger un commentaire. À l'origine, Python n'a pas la capacité de commenter plusieurs lignes, mais mettre une chaîne dans votre programme n'a aucun effet, vous pouvez donc l'utiliser pour écrire des commentaires sur plusieurs lignes. En outre, les commentaires sur plusieurs lignes peuvent être laissés sous forme de chaîne de documentation.
Python
#Commentaire d'une ligne
'''
Commentaire sur plusieurs lignes
'''
"""
Commentaire sur plusieurs lignes
"""
def func():
"""
Commentaire du programme, etc.
"""
help(func)
print(func.__doc__)
Go
//Commentaire d'une ligne
/*
Commentaire sur plusieurs lignes
*/
Python est un langage typé dynamiquement, vous n'avez donc pas besoin de déclarer le type d'une variable.
Python
n = 10
name = "hoge"
#Définir collectivement
x, y, z = 1, 2, 3
a = b = c = 1
Dans le cas de Go, vous devez d'abord faire attention au premier caractère du nom de la variable.
Cela s'applique également aux constantes et aux fonctions. Go est un langage de typage statique, mais il existe des définitions explicites et implicites.
Définissez-le comme var [nom de la variable] [type de variable]
.
Go
var n int
n = 1
//Définir collectivement
var x, y, z int
x, y, z = 1, 2, 3
var (
x, y int
name string
)
x, y, name = 1, 2, "hoge"
//Déclarez le type et attribuez la valeur en même temps
var n int = 1
Définissez-le comme «[nom de la variable]: = [valeur]» ou «var [nom de la variable] = [valeur]». L'affectation d'une valeur déduit implicitement le type de la variable.
Go
n := 1
//Le type peut être omis même dans la définition en utilisant var
var n = 1
//Définir collectivement
x, y, name := 1, 2, "hoge"
var (
x = 1
y = 2
name = "hoge"
)
Python n'a pas de mots clés pour définir les constantes. Par convention, seules les lettres majuscules et les barres inférieures représentent des constantes.
Python
PI = 3.14
MAX_NUM = 100
Go utilise const
pour définir les constantes. Vous pouvez utiliser l'identifiant ʻiota` pour générer une séquence d'entiers.
Tenter de changer la valeur d'une constante entraînera une erreur.
Go
const Pi = 3.14
const MaxNum = 100
// ()Définir collectivement dans
const (
Pi = 3.14
MaxNum = 100
)
const (
X = iota // 0
Y // 1
Z // 2
)
//Lors de la spécification du numéro de départ
const (
X = iota + 10 // 10
Y // 11
Z // 12
)
Les listes Python peuvent être écrites très simplement. Ce qui suit est l'utilisation de base.
Python
#Définition
numbers = [1, 2, 3]
#Ajouter un élément
numbers.append(6)
numbers.insert(3, 5) # numbers: [1, 2, 3, 5, 6]
#Nombre d'éléments
len(numbers)
#Supprimer l'élément
numbers.remove(3) # numbers: [1, 2, 5, 6]
numbers.pop(1) # numbers: [1, 5, 6]
del numbers[0] # numbers: [5, 6]
#Combiner des listes
numbers += [3, 4] # numbers: [5, 6, 3, 4]
numbers.extend([1, 2]) # numbers: [5, 6, 3, 4, 1, 2]
#Rechercher des éléments
print(6 in numbers) # True
print(numbers.index(6)) # 1
#Trier la liste
numbers.sort() # numbers: [1, 2, 3, 4, 5, 6]
numbers.sort(reverse=True) # numbers: [6, 5, 4, 3, 2, 1]
Le type de baie de Go ne peut pas être mis à l'échelle vers le haut ou vers le bas. Les structures de données telles que les listes Python sont équivalentes aux tranches dans Go.
La fonction ʻappendest souvent utilisée pour les opérations de découpage. Pour **
...`, voir [Argument de longueur variable de la fonction](# Argument de longueur variable). ** **
Go
//Le tableau ne peut pas être redimensionné
array := [3]int{1, 2, 3}
fmt.Println(array[0]) // 1
fmt.Println(array[1:3]) // [2 3]
//tranche
n1 := []int{} // n1: []
n2 := make([]int, 0) // n2: []
numbers := []int{1, 2, 3}
//Ajouter un élément
numbers = append(numbers, 6) // numbers: [1 2 3 6]
numbers = append(numbers[0:3], append([]int{5}, numbers[3:]...)...) // numbers: [1 2 3 5 6]
//Nombre d'éléments
len(numbers)
//Supprimer l'élément
numbers = append(numbers[0:2], numbers[3:]...) // numbers: [1 2 5 6]
numbers = numbers[2:] // numbers: [5 6]
//Joindre des séquences
numbers = append(numbers, []int{3, 4, 1, 2}...) // numbers: [5 6 3 4 1 2]
//Rechercher des éléments
//Il n'y a pas d'équivalent à l'index Python, alors écrivez-le vous-même
fmt.Println(IndexOf(numbers, 6)) // 1
func IndexOf(s []int, n int) int {
for i, v := range s {
if n == v {
return i
}
}
return -1
}
//Trier le tableau
//Utilisez le package de tri
sort.Ints(numbers)
fmt.Println(numbers) // [1 2 3 4 5 6]
sort.Sort(sort.Reverse(sort.IntSlice(numbers)))
fmt.Println(numbers) // [6 5 4 3 2 1]
Python utilise une structure de données appelée dictionnaire.
Python
#Définition
dic = {'hoge': 1, 'fuga': 2, 'piyo': 3}
list1 = [('hoge', 1), ('fuga', 2), ('piyo', 3)]
dic2 = dict(list1) #Identique à la valeur dic
dic['hoge']
dic.get('hoge')
#Ajouter et supprimer des éléments
dic['foo'] = 4
dic.setdefault('bar', 5)
dic.pop('hoge') # {'fuga': 2, 'piyo': 3, 'foo': 4, 'bar': 5}
del dic['fuga'], dic['piyo'] # {'foo': 4, 'bar': 5}
#Nombre d'éléments
len(dic)
#Confirmation de l'existence de la clé
'foo' in dic
#Récupération des clés et des valeurs
list(dic.keys()) # ['foo', 'bar']
list(dic.values()) # [4, 5]
for k, v in dic.items():
print(k, v)
La carte Go est l'équivalent du dictionnaire Python. Il est défini dans le format suivant.
type d'élément map [type de clé ]
Go
//Définition
dic := map[string]int{"hoge": 1, "fuga": 2, "piyo": 3}
dic2 := make(map[string]int)
fmt.Println(dic) // map[fuga:2 hoge:1 piyo:3]
fmt.Println(dic2) // map[]
//Ajouter et supprimer des éléments
dic["foo"] = 4
delete(dic, "hoge")
fmt.Println(dic) // map[foo:4 fuga:2 piyo:3]
//Nombre d'éléments
len(dic)
//Confirmation de l'existence de la clé
_, exist := dic["foo"]
fmt.Println(exist) // true
if value, exist := dic["foo"]; exist {
fmt.Println(value) // 4
}
//Récupération des clés et des valeurs
for k, v := range dic {
fmt.Println(k, v)
}
Python n'a pas d'instruction switch. Utilisez ʻif ... elif ... else` à la place. Il existe également une manière d'écrire appelée expression conditionnelle (opérateur ternaire).
6.12. Expressions conditionnelles https://docs.python.org/ja/3/reference/expressions.html#conditional-expressions
Les opérateurs logiques utilisent ʻand, ʻou
, not
.
Python
x, y = 1, 2
if x > y:
print('x > y')
elif x < y:
print('x < y')
else:
print('x == y')
n = 10
#Expression conditionnelle
result = "positive" if n > 0 else "negative or zero"
Il existe deux types de branchement conditionnel dans Go, if et switch, et vous ne pouvez définir des variables valides que dans ce bloc en écrivant if avec une simple instruction.
Il n'y a pas d'opérateur ternaire, mais vous pouvez l'écrire comme ça avec map.
L'opérateur logique est&&
,||
,!
Utilisez le.
Go
x, y := 1, 2
if x > y {
fmt.Println("x > y")
} else if x < y {
fmt.Println("x < y")
} else {
fmt.Println("x == y")
}
#Si avec une simple phrase
if x, y := 1, 2; x > y {
fmt.Println("x > y")
} else if x < y {
fmt.Println("x < y")
} else {
fmt.Println("x == y")
}
#instruction switch
x, y := 1, 2;
switch {
case x > y:
fmt.Println("x > y")
case x < y:
fmt.Println("x < y")
default:
fmt.Println("x == y")
}
n := 10
#Comment écrire comme un opérateur ternaire
result := map[bool]string{true: "positive", false: "negative"}[n > 0]
Utilisez for et while pour la boucle Python.
Python
sum = 0
for num in range(1, 11):
sum += num
num, sum = 1, 0
while num <= 10:
sum += num
num += 1
#boucle infinie
num, sum = 1, 0
while True:
sum += num
num += 1
if num > 10:
break
La seule boucle Go est pour, mais vous pouvez également la contrôler comme while.
Go
sum := 0
for num := 0 ; num <= 10 ; num++ {
sum += num
}
// while
num, sum := 1, 0
for num <= 10 {
sum += num
num++
}
//boucle infinie
num, sum := 1, 0
for {
sum += num
num++
if num > 10 {
break
}
}
Les fonctions Python sont définies avec def
. La définition de fonction doit être écrite avant l'exécution de l'appel de fonction.
Il existe les usages suivants.
Python
def greet(name="World"):
print("Hello, " + name)
greet()
greet("Alice")
greet(name="Alice")
#Variable de longueur variable
def greet(*names):
for name in names:
print("Hello, " + name)
greet("Alice", "Bob", "Carol")
#Valeurs de retour multiples
def cal(a, b):
add = a + b
mul = a * b
return add, mul
add, mul = cal(10, 5)
Les fonctions Go sont définies avec func
.
func [nom de la fonction]([définition de l'argument]) [type de retour] {[corps de la fonction]}
Il n'y a pas d'arguments par défaut ou de mot-clé, mais ils présentent les caractéristiques suivantes:
defer
sont exécutées à la fin de la fonction. Si plusieurs définitions sont faites, elles seront appelées à partir de la fin.Les arguments de longueur variable pour les fonctions sont définis comme «[nom de l'argument] ... [type d'argument]».
Et si vous passez une tranche comme argument de longueur variable, vous devez ajouter ...
après la variable pour développer la tranche.
Go
func main() {
add, mul := cal(10, 5)
fmt.Println(add, mul) // 15 50
add, mul = calc(10, 5)
fmt.Println(add, mul) // 15 50
greet("Alice", "Bob", "Carol")
names := []string{"Alice", "Bob", "Carol"}
greet(names...) //Passer une tranche comme argument de longueur variable
testDefer() // BDCA
}
//Forme basique
func cal(a int, b int) (int, int) {
add := a + b
mul := a * b
return add, mul
}
//Valeur de retour nommée
//Si les types d'arguments sont les mêmes, vous pouvez les écrire tous ensemble
func calc(a, b int) (add int, mul int) {
add = a + b
mul = a * b
return
}
//Fonctions sans valeur de retour
//Argument de longueur variable
func greet(names ...string) {
for _, name := range names {
fmt.Println("Hello,", name)
}
}
//différer l'exécution différée
func testDefer() {
defer fmt.Print("A")
fmt.Print("B")
defer fmt.Print("C") //C est sorti avant A
fmt.Print("D")
}
Python utilise la syntaxe «try-except» pour intercepter et gérer les exceptions.
Python
def doDivision(x, y):
try:
result = x / y
except Exception as e:
result = None
print("except:" + e.args[0])
else: #Exécuter à la fin normale
print("else")
finally: #Toujours courir à la sortie
print("finally")
return result
doDivision(10, 2)
# else
# finally
doDivision(10, 0)
# except:test exception
# finally
Il n'y a pas de mécanisme d'exception comme «try-except» dans Go. Au lieu de cela, il utilise la propriété de pouvoir renvoyer plusieurs valeurs de retour d'une fonction pour détecter une erreur en retournant si une erreur s'est produite («interface d'erreur») dans le cadre de la valeur de retour. L'interface d'erreur est définie comme suit: https://golang.org/pkg/builtin/#error
Go interface d'erreur
type error interface {
Error() string
}
L'exemple suivant utilise la fonction New
du package ʻerrors pour générer le ʻerror type
.
Vous pouvez également utiliser defer
pour obtenir le même comportement que celui de Python enfin
.
Go
package main
import (
"fmt"
"errors"
)
func main() {
_, err := doDivision(10, 2)
if (err != nil) {
//La gestion des erreurs
}
// defer
_, err = doDivision(10, 0)
if (err != nil) {
//La gestion des erreurs
}
// error
// defer
}
func doDivision(i, j int) (result int, err error) {
defer fmt.Println("defer") //Toujours courir à la sortie
if j == 0 {
fmt.Println("error")
err = errors.New("Divided by Zero")
return
}
result = i / j
return
}
De plus, Go a également un mécanisme de gestion des erreurs appelé panic / recover
, mais je l'omettrai ici.
Voici un exemple de classe Python simple.
Python
class Player:
def __init__(self, id, name):
self.id = id
self.name = name
self.__hp = 100
@property
def hp(self):
return self.__hp
def consume_hp(self, num):
self.__hp -= num
player = Player(10001, "Alice")
print(player.hp) # 100
player.consume_hp(10)
print(player.hp) # 90
Go n'a pas de syntaxe équivalente à class
en Python, mais il utilise une structure qui gère les variables associées ensemble dans un rôle similaire.
Vous pouvez définir des méthodes pour la structure. Contrairement aux fonctions, les méthodes nécessitent le type de récepteur et son nom de variable.
L'exemple suivant définit une méthode appelée consumeHp
pour un type de pointeur appelé * Player
.
Go
//Structure du type de joueur
type Player struct{
ID int
Name string
Hp int
}
//constructeur
func newPlayer(id int, name string) Player {
return Player{ID: id, Name: name, Hp: 100}
}
// *Méthode du type de joueur
func (p *Player) consumeHp(num int) {
p.Hp -= num
}
func main() {
p := newPlayer(10001, "Alice")
fmt.Println(p.Hp) // 100
p.consumeHp(10)
fmt.Println(p.Hp) // 90
}
Enfin, j'écrirai un peu sur le multithreading.
Ce qui suit est un exemple simple d'utilisation du module threading
pour générer un thread et passer des données dans une file d'attente.
Python
import threading
import time
from queue import Queue
def worker(a, b, q):
time.sleep(1)
result = a + b
q.put(result) #Mettre des éléments dans la file d'attente
print("result:", result)
q = Queue()
thread = threading.Thread(target=worker, args=(2, 3, q))
thread.start()
thread.join()
print("main thread")
result = q.get() #Supprimer des éléments de la file d'attente
q.task_done()
print("received:", result) # received: 5
Faisons de même avec Go.
Dans Go, un thread léger, goroutine, est implémenté pour s'exécuter en parallèle. L'écriture de go f (x)
démarre une nouvelle goroutine et exécute la fonction.
Il utilise une structure de données appelée canal pour transmettre des données entre les goroutines. Le nom du type de canal s'écrit chan [type de données]
.
Go
package main
import (
"fmt"
"time"
)
func newThread(a, b int, ch chan int) {
time.Sleep(1000)
result := a + b
ch <- result //Envoyer des données au canal
fmt.Println("result:", result)
}
func main() {
ch := make(chan int) //Générer une chaîne
go newThread(2, 3, ch) //Run newThread dans un nouveau goroutine
fmt.Println("main thread")
result := <-ch //Recevoir les données du canal
close(ch)
fmt.Println("received:", result) // received: 5
}
J'ai vu la grammaire du langage Go par rapport à Python. Bien que Go soit un langage à typage statique, il est également aussi facile à écrire qu'un langage à typage dynamique tel que Python. Comme on dit que Go est influencé par divers langages, je pense que quiconque comprend le langage C peut immédiatement comprendre les pointeurs et les structures de Go. Je ne pourrais pas m'étendre sur la goroutine et le canal, qui sont importants pour le traitement parallèle, mais j'aimerais les réécrire.