Une histoire à laquelle j'étais accro en spécifiant nil comme argument de fonction dans Go

Préface

Je pense que l'histoire de go's nil est la nième décoction, mais j'écrirai un article pour commémorer ma dépendance.

Comme le code réel est un peu plus long et se trouve dans le cadre, il était difficile d'identifier la cause, mais je n'écrirai que l'essentiel.

J'ai fait une méthode comme celle-ci (exemple d'échec)

Au fait, j'avais l'intention d'être une fonction wrapper car je lance HTTPRequest plusieurs fois dans le code de test.

func Request(method, url string, body *strings.Reader) error {
	request, err := http.NewRequest(method, url, body)
	if err != nil {
		return err
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := new(http.Client)
	resp, _ := client.Do(request)
	defer resp.Body.Close()
	byteArray, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(byteArray))
	return nil
}

Je suppose que vous utilisez cette méthode de cette façon.

	
func main() {

	values := url.Values{
		"hoge": []string{"fuga"},
	}

	err := Request("POST", "https://google.com", strings.NewReader(values.Encode()))
	if err != nil {
		log.Fatal(err)
	}

}

Pour le troisième argument de Request, ~~ En gros ~~ j'ai spécifié le type de retour des chaînes.NewReader tel quel sans penser à rien.

Spécifiez nil

Maintenant, quand il n'y a rien à envoyer de paramètres dans POST


	err := Request("POST", "https://google.com", nil)
	if err != nil {
		log.Fatal(err)
	}

Je précise, mais quand j'exécute ça

Il plante avec une erreur d'exécution.

strings.(*Reader).Len(...)
        /usr/local/Cellar/go/1.15.3/libexec/src/strings/reader.go:26
net/http.NewRequestWithContext(0x1314620, 0xc00001a0b0, 0x12baeec, 0x3, 0x12be7e1, 0x12, 0x13102c0, 0x0, 0x121018d, 0x0, ...)
        /usr/local/Cellar/go/1.15.3/libexec/src/net/http/request.go:889 +0x2a4
net/http.NewRequest(...)
        /usr/local/Cellar/go/1.15.3/libexec/src/net/http/request.go:813
main.Request(0x12baeec, 0x3, 0x12be7e1, 0x12, 0x0, 0x0, 0x0)

Au fait, ce n'est pas grave si vous spécifiez nil directement dans le troisième argument de http.NewRequest.

	req, err := http.NewRequest("POST", "https://google.com", nil)
	if err != nil {
		log.Fatal(err)
	}

Quelle est la raison de l'erreur?

Comme vous pouvez le voir en parcourant IntelliJ IDEA,

https://github.com/golang/go/blob/f2eea4c1dc37886939c010daff89c03d5a3825be/src/net/http/request.go#L887

if body != nil {

Go's nil est une sémantique typée, donc il entre dans la fonction avec le type de * strings.NewReader, même si le corps lui-même est nul dans le code ci-dessous. Le type du corps lui-même est * strings.NewReader et la déclaration du corps est io.Reader. Le jugement nul est vrai (involontairement?), Et cela signifie qu'il est dans le si et une erreur se produit.

référence: https://qiita.com/umisama/items/e215d49138e949d7f805

Si nil est spécifié dans l'argument de la fonction, il devient le type d'argument de la déclaration de fonction.

req, err := http.NewRequest("POST", "https://google.com", nil)

Maintenant le nil spécifié ici, à partir de la définition de NewRequest Il devient nul de io.Reader. (Io.Reader est également saisi dans l'interface)

Que devrais-je faire

func Request(method, url string, body *strings.Reader) Argument de func Request(method, url string, body io.Reader)

Cela aurait dû l'être, donc même s'il s'agit d'une fonction jetable dans le test, Il était sûr de faire correspondre l'argument de la fonction au type de la fonction utilisée à l'intérieur, pas au type de l'appelant.

Conclusion

Lorsque nil est spécifié dans le troisième argument de http.NewRequest, spécifiez-le comme étant le type de io.Reader.

Déclarez les arguments de fonction aussi proches que possible du type appelé à l'intérieur.

On dit souvent que nul n'y est accro, mais je pensais que je ne le remarquerais que si j'en étais réellement accro.

Recommended Posts

Une histoire à laquelle j'étais accro en spécifiant nil comme argument de fonction dans Go
Ce à quoi j'étais accro lors de la création d'applications Web dans un environnement Windows
[Fabric] J'étais accro à l'utilisation de booléen comme argument, alors notez les contre-mesures.
Une histoire à laquelle j'étais accro chez np.where
Une histoire à laquelle j'étais accro après la communication SFTP avec python
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
Le record auquel j'étais accro en mettant MeCab dans Heroku
Une note à laquelle j'étais accro lors de l'émission d'un bip sous Linux
Une note à laquelle j'étais accro lors de la création d'une table avec SQL Alchemy
Créez une fonction pour obtenir le contenu de la base de données dans Go
Quand j'ai essayé de gratter en utilisant des requêtes en python, j'étais accro à SSLError, donc un mémo de contournement
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
Une histoire à laquelle j'étais accro à essayer d'installer LightFM sur Amazon Linux
Une histoire à laquelle j'étais accro à essayer d'obtenir une URL de vidéo avec tweepy
Le nom du fichier était mauvais en Python et j'étais accro à l'importation
[Python] J'ai essayé d'obtenir le nom du type sous forme de chaîne de caractères à partir de la fonction type
Une note à laquelle j'étais accro lors de l'exécution de Python avec Visual Studio Code
[Mots qui m'ont été épelés quand j'étais en première année ①] Je n'ai pas peur de créer un environnement de programmation.
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
J'étais accro au grattage avec Selenium (+ Python) en 2020
Une simple différence lors du passage d'un pointeur comme argument de fonction
J'étais accro à essayer logging.getLogger avec Flask 1.1.x
Ce à quoi j'étais accro lors de l'utilisation de Python tornado
J'étais sobrement accro à appeler awscli à partir d'un script Python 2.7 enregistré dans crontab
Une histoire qui était pratique lorsque j'ai essayé d'utiliser le module d'adresse IP python
Notez que j'étais accro au script npm ne passant pas dans l'environnement de vérification
Ce à quoi j'étais accro en combinant l'héritage de classe et l'héritage de table commune dans SQLAlchemy
Ce que j'ai fait quand j'étais en colère de le mettre avec l'option enable-shared
Lorsqu'une variable locale portant le même nom que la variable globale est définie dans la fonction
En ce qui concerne le type de processus écrit dans le fichier Procfile de honcho, j'y ai été accro pendant plus d'une heure parce que je ne pouvais pas utiliser -, donc je l'écrirai comme une émission.
[Petite histoire] Une mesure minutieuse lorsque vous devez exécuter une fonction avant l'importation en Python
Des mots qui m'intéressaient en tant que débutant en programmation
Une histoire qui a disparu quand j'ai spécifié un chemin commençant par tilda (~) en python open
Ce à quoi j'étais accro lorsque l'utilisateur de traitement est passé à Python
Je l'ai écrit en langage Go pour comprendre le principe SOLID
J'ai essayé d'implémenter la fonction d'envoi de courrier en Python
L'histoire quand j'étais accro à Caused by SSLError ("Impossible de se connecter à l'URL HTTPS car le module SSL n'est pas disponible.")
Une histoire sur l'écriture d'AWS Lambda et de devenir un peu accro aux valeurs par défaut des arguments Python
Notez que j'étais accro à accéder à la base de données avec mysql.connector de Python en utilisant une application Web
Lorsque j'ai mis Django dans mon répertoire personnel, je suis devenu accro à un fichier statique avec une erreur d'autorisation
[Linux] Je souhaite connaître la date à laquelle l'utilisateur s'est connecté
Précautions lors de l'utilisation d'une liste ou d'un dictionnaire comme argument par défaut
Ce à quoi j'étais accro en présentant ALE à Vim pour Python
Ce à quoi j'étais accro avec json.dumps dans l'encodage base64 de Python
J'ai écrit une fonction pour charger le script d'extension Git en Python
Utilisation de lambda (lors du passage d'une fonction comme argument d'une autre fonction)
L'histoire selon laquelle le gardien était confiné lorsque le laboratoire a été converti à l'IoT
J'étais accro aux variables de classe et aux variables d'instance erronées en Python
J'ai fait une commande pour afficher un calendrier coloré dans le terminal
Une histoire accro aux pipelines Azure
J'étais accro au multitraitement + psycopg2
Je veux éviter les problèmes de saisie lors du débogage de l'exemple de vérification des compétences de Paiza dans un environnement local tel que Jupyter [Python]
[Python] Quand j'ai essayé de créer un outil de décompression avec un fichier zip que je connaissais juste, j'étais accro à sys.exit ()
L'histoire de la recherche d'un magasin BOT (AI LINE BOT) pour Go To EAT dans la préfecture de Chiba (1)
Je veux charger le projecteur pytest en tant que bibliothèque ailleurs (pytest peut ne pas exister dans l'environnement)