In dit artikel legt Iain Cambridge uit waarom het riskant is om GitHub-URL's direct als namespace voor Go-code te gebruiken. Deze praktijk creëert een sterke afhankelijkheid van de hostingprovider (vendor lock-in), waardoor het verplaatsen van projecten naar alternatieven zoals GitLab of Azure DevOps een complexe taak wordt omdat de broncode zelf moet worden gewijzigd.
De voorgestelde oplossing is het gebruik van aangepaste domeinen (vanity URLs). Door een eigen domein te gebruiken, blijft de import-regel in de code constant, terwijl de backend-locatie eenvoudig kan worden gewijzigd zonder impact op de eindgebruiker. De auteur ondersteunt zijn betoog met een concrete implementatie via een Nginx-configuratie en een HTML-bestand met specifieke meta-tags (go-import en go-source) om de Go-tooling correct naar de uiteindelijke repository te leiden.
Koppel je Go-code niet aan GitHub
Een van de goede functies van Go is dat je je code namespace't met de locatie waar de code kan worden opgehaald. Dit betekent dat als je je Go-code host op http://github.com/thetrueares/boneclone, je de regel import “github.com/thetrueares/boneclone” gebruikt en Go deze via git ophaalt. Dit maakt het zeer eenvoudig om te weten waar je bugs moet melden voor open source-bibliotheken en maakt het ophalen en distribueren van Go-bibliotheken erg makkelijk zonder een centraal pakketbeheersysteem. Voor velen is dit simpelweg de locatie van de git-hosting, maar dit heeft nadelen. Je zou je eigen aangepaste domein moeten gebruiken, en ik zal uitleggen waarom.
Het probleem
Het belangrijkste probleem met het gebruik van je git-hostinglocatie is dat je code nu gekoppeld is aan een hostingprovider. Dat wil zeggen: als je je git-hosting verplaatst naar GitLab, moet je je code wijzigen! Anders haal je de oude versie op. Dit kan ertoe leiden dat je geen hostingprovider kunt wijzigen vanwege de hoeveelheid overhead die gepaard gaat met het overstappen. Je eindigt dus letterlijk met code die gekoppeld is aan GitHub. Dat klinkt volkomen krankzinnig, maar het is iets wat in de Go-community vrijwel de facto standaard is.
Ik heb gezien dat dit probleem een enorm issue werd voor een bedrijf dat tegelijkertijd GitLab, GitHub en Azure Devops gebruikte. Omdat het wijzigen van de locatie van de code zo'n grote taak voor hen was en ze geen "tijd hadden", was het voor hen makkelijker om op drie platforms tegelijk te werken. Dit is waarom ik Boneclone heb gebouwd om skeleton-code replicatie over meerdere git-hostingplatforms tegelijkertijd te beheren. Dit probleem kostte het bedrijf dus letterlijk geld, aangezien ze tegelijkertijd voor drie hostingdiensten moesten betalen.
De oplossing
De oplossing is om aangepaste domeinen te gebruiken zoals go.iain.rocks, go.uber.org, go.mongodb.org, etc. Hiermee kun je simpelweg wijzigen waar die domeinen naartoe wijzen. Bijvoorbeeld: go.iain.rocks/boneclone wijst naar github.com/thetrueares/boneclone, en als ik overstap naar GitLab verandert er voor de eindgebruikers niets; het installatiecommando blijft hetzelfde.
Naar mijn mening zou elk commercieel softwareontwikkelteam dat Go gebruikt, aangepaste domeinen moeten gebruiken voor het namespacen van hun interne bibliotheken en pakketten. Het is een eenvoudige manier om elke zinloze koppeling te voorkomen.
Hier is een kopie van mijn configuraties, zodat je dit ook voor jouw projecten kunt instellen.
Nginx.conf
server {
server_name go.iain.rocks;
root /var/www/go.iain.rocks;
index index.html;
location / {
# Check if the query string does NOT contain 'go-get=1'.
# The '~' is for a case-sensitive match.
if ($args !~ go-get=1) {
# This is a human visitor. Issue a permanent redirect to GitHub.
# $request_uri will be the path, e.g., /boneclone
return 301 https://github.com/that-guy-iain$request_uri;
}
# If it's the Go tool (with ?go-get=1), serve the HTML file as before.
try_files $uri $uri/ =404;
}
# --- Your SSL configuration from Certbot should remain here ---
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/go.iain.rocks/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/go.iain.rocks/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
# The HTTP to HTTPS redirect block should also remain.
server {
listen 80;
listen [::]:80;
server_name go.iain.rocks;
return 301 https://$host$request_uri;
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="go-import" content="go.iain.rocks/boneclone git https://github.com/that-guy-iain/boneclone">
<meta name="go-source" content="go.iain.rocks/boneclone https://github.com/that-guy-iain/boneclone https://github.com/that-guy-iain/boneclone/tree/master{/dir} https://github.com/that-guy-iain/boneclone/blob/master{/dir}/{file}#L{line}">
</head>
<body>
</body>
</html>
Koppel je Go-code niet aan GitHub
Een van de goede functies van Go is dat je je code namespace't met de locatie waar de code kan worden opgehaald. Dit betekent dat als je je Go-code host op http://github.com/thetrueares/boneclone, je de regel import “github.com/thetrueares/boneclone” gebruikt en Go deze via git ophaalt. Dit maakt het zeer eenvoudig om te weten waar je bugs moet melden voor open source-bibliotheken en maakt het ophalen en distribueren van Go-bibliotheken erg makkelijk zonder een centraal pakketbeheersysteem. Voor velen is dit simpelweg de locatie van de git-hosting, maar dit heeft nadelen. Je zou je eigen aangepaste domein moeten gebruiken, en ik zal uitleggen waarom.
Het probleem
Het belangrijkste probleem met het gebruik van je git-hostinglocatie is dat je code nu gekoppeld is aan een hostingprovider. Dat wil zeggen: als je je git-hosting verplaatst naar GitLab, moet je je code wijzigen! Anders haal je de oude versie op. Dit kan ertoe leiden dat je geen hostingprovider kunt wijzigen vanwege de hoeveelheid overhead die gepaard gaat met het overstappen. Je eindigt dus letterlijk met code die gekoppeld is aan GitHub. Dat klinkt volkomen krankzinnig, maar het is iets wat in de Go-community vrijwel de facto standaard is.
Ik heb gezien dat dit probleem een enorm issue werd voor een bedrijf dat tegelijkertijd GitLab, GitHub en Azure Devops gebruikte. Omdat het wijzigen van de locatie van de code zo'n grote taak voor hen was en ze geen "tijd hadden", was het voor hen makkelijker om op drie platforms tegelijk te werken. Dit is waarom ik Boneclone heb gebouwd om skeleton-code replicatie over meerdere git-hostingplatforms tegelijkertijd te beheren. Dit probleem kostte het bedrijf dus letterlijk geld, aangezien ze tegelijkertijd voor drie hostingdiensten moesten betalen.
De oplossing
De oplossing is om aangepaste domeinen te gebruiken zoals go.iain.rocks, go.uber.org, go.mongodb.org, etc. Hiermee kun je simpelweg wijzigen waar die domeinen naartoe wijzen. Bijvoorbeeld: go.iain.rocks/boneclone wijst naar github.com/thetrueares/boneclone, en als ik overstap naar GitLab verandert er voor de eindgebruikers niets; het installatiecommando blijft hetzelfde.
Naar mijn mening zou elk commercieel softwareontwikkelteam dat Go gebruikt, aangepaste domeinen moeten gebruiken voor het namespacen van hun interne bibliotheken en pakketten. Het is een eenvoudige manier om elke zinloze koppeling te voorkomen.
Hier is een kopie van mijn configuraties, zodat je dit ook voor jouw projecten kunt instellen.
Nginx.conf
server {
server_name go.iain.rocks;
root /var/www/go.iain.rocks;
index index.html;
location / {
# Check if the query string does NOT contain 'go-get=1'.
# The '~' is for a case-sensitive match.
if ($args !~ go-get=1) {
# This is a human visitor. Issue a permanent redirect to GitHub.
# $request_uri will be the path, e.g., /boneclone
return 301 https://github.com/that-guy-iain$request_uri;
}
# If it's the Go tool (with ?go-get=1), serve the HTML file as before.
try_files $uri $uri/ =404;
}
# --- Your SSL configuration from Certbot should remain here ---
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/go.iain.rocks/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/go.iain.rocks/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
# The HTTP to HTTPS redirect block should also remain.
server {
listen 80;
listen [::]:80;
server_name go.iain.rocks;
return 301 https://$host$request_uri;
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="go-import" content="go.iain.rocks/boneclone git https://github.com/that-guy-iain/boneclone">
<meta name="go-source" content="go.iain.rocks/boneclone https://github.com/that-guy-iain/boneclone https://github.com/that-guy-iain/boneclone/tree/master{/dir} https://github.com/that-guy-iain/boneclone/blob/master{/dir}/{file}#L{line}">
</head>
<body>
</body>
</html>