Dealing with the scope of variables: inside loop - go

As a JS dev jumping right into Go, I've hit a deadend trying to print multiple descriptions if the length of commits is more than one. I don't have much time left to complete this and I've been searching for longer than I wish. Any idea on how I could either restructure this or get this to work?
case github.PushPayload:
push := payload.(github.PushPayload)
repo := push.Repository.Name
owner := push.Repository.Owner.Login
ownerUrl := push.Repository.Owner.HTMLURL
ownerAvatar := push.Repository.Owner.AvatarURL
ref := push.Ref
refTrim := strings.Replace(ref, "/.*/", "", -1)
commits := push.Commits
for _, commit := range commits {
message := commit.Message
url := commit.URL
id := commit.ID
idShort := id[0:6]
committer := commit.Committer.Username
description := "[`" + idShort + "`](" + url + ") " + message + " - " + committer
}
if len(commits) == 1 {
discord.ChannelMessageSendEmbed(channelID, &discordgo.MessageEmbed{
Color: 0x00B1FF,
Description: description,
Title: "[" + repo + ":" + refTrim + "] 1 new commit! 🔧",
Author: &discordgo.MessageEmbedAuthor{
Name: owner,
URL: ownerUrl,
IconURL: ownerAvatar,
},
})
} else {
discord.ChannelMessageSendEmbed(channelID, &discordgo.MessageEmbed{
Color: 0x00B1FF,
Description: description,
Title: "[" + repo + ":" + refTrim + "] " + string(len(commits)) + " new commits! ⚒️",
Author: &discordgo.MessageEmbedAuthor{
Name: owner,
URL: ownerUrl,
IconURL: ownerAvatar,
},
})
}
PS: Ignore string(len(commits)) I know that's incorrect, I'm stuck trying to figure this out first and foremost. Also ignore: refTrim := strings.Replace(ref, "/.*/", "", -1), which isn't correct either.

you have to declare description variable before the loop and then add commit descriptions to it as below inside the loop.
Note: I emitted other code blocks here.
description := ""
for _, commit := range commits {
description = description + "commit description here"
}
description += "commit description here" also can be used inside the loop. But I have added above to more understanding.

Related

panic: runtime error: index out of range processing file

I'm trying to make a function that reads a collection of data from JSON file, but I keep receiving this error
panic: runtime error: index out of range
and it's not importing all the data from json file,
I think there's something wrong in my for loop.
// read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile)
// initialize Int array
var interns Int
// initialize Com array
var companies Com
// unmarshal byteArray
json.Unmarshal(byteValue, &interns)
json.Unmarshal(byteValue, &companies)
// iterate through every student within our students array and
// print out the student ID, first & last name
for i := 0; i < len(interns.Int); i++ {
fmt.Println("Student first name: " + interns.Int[i].Name.FirstName)
fmt.Println("Student last name: " + interns.Int[i].Name.LastName)
fmt.Println("Company name: " + companies.Com[i].CompanyName)
fmt.Println("Company email address: " + companies.Com[i].CompanyEmail + "\n")
}
Because you are using len of Int array to iterate Com array while len of Com array is different so the program will panic when iterate to an index that Com array is not available
//Program panics if [i] is not valid
fmt.Println("Company name: " + companies.Com[i].CompanyName)
fmt.Println("Company email address: " + companies.Com[i].CompanyEmail + "\n")
Split the loop into two to iterate and it will works
// iterate Int array
for i := 0; i < len(interns.Int); i++ {
fmt.Println("Student first name: " + interns.Int[i].Name.FirstName)
fmt.Println("Student last name: " + interns.Int[i].Name.LastName)
}
// iterate Com array
for i := 0; i < len(companies.Com); i++ {
fmt.Println("Company name: " + companies.Com[i].CompanyName)
fmt.Println("Company email address: " + companies.Com[i].CompanyEmail + "\n")
}

Problem while taking user input via fmt.Scanln() in golang

I m trying to take an input from the user through my console in golang by using fmt.Scanln(). It is working fine under normal circumstances. However, whenever I take input in a loop, the inputs are correct in the first iteration but during the next iterations of a loop, an extra smiley is added in the front of the received string. I don't know what the problem is. Will be very thankful if anyone proposes some solution.
func (a *Block) fillBlock() {
fmt.Println("Block Details:")
fmt.Print("Enter Block Name: ")
fmt.Scanln(&a.Data)
for i := 0; i < Students; i++ {
fmt.Print(i, "Enter Student Roll# ")
fmt.Scanln(&a.Grades[i].Rollno)
fmt.Print(i, "Enter Student Grade# ")
fmt.Scanln(&a.Grades[i].Grade)
}
fmt.Println("\nInput Data:")
fmt.Println("Data: ",a.Data)
// Iterating over each student
for i := 0; i < Students && (a.Grades[i].Rollno != "" && a.Grades[i].Grade != ""); i++ {
fmt.Println("Rollno: " + string(i) + a.Grades[i].Rollno)
fmt.Println("Grade: " + string(i) + a.Grades[i].Grade)
}
}
This is wrong:
fmt.Println("Rollno: " + string(i) + a.Grades[i].Rollno)
Instead, use
fmt.Println("Rollno: " + strconv.Itoa(i) + a.Grades[i].Rollno)
Or, better:
fmt.Printf("Rollno: %d %s\n",i a.Grades[i].Rollno)

grafana scripted influxdb

I am using grafana 4 and influxDB.
I need to show a graph of say CPU usage for a certain host by building the parameters in the URL like this
http://my_grafana:3000/dashboard/script/scripted.js?name=CPULoad&host=ussd1
i am trying to use scripted dashboards for this but i cannot figure out how to tell scripted.js where to look for the data of CPULoad.
can anyone give me some pointers?
regards,
Martin
Well I found out how it works, but I have to say it is wierd that it is not documented anywhere and it involves a little modification to the source code...
A little bit of context first
I have a influxdb database called "Nagios". Inside this database, I have several series. a show series in influxdb shows the following
> show series
key
---
nagios.CPULoad,hostname=cbba.storage,state=OK
nagios.CPULoad,hostname=ussd1,state=OK
nagios.CPULoad,hostname=ussd2,state=OK
nagios.CPULoad,hostname=ussd3,state=OK
nagios.CPULoad,hostname=ussd4,state=OK
The structure of the data in series CPULoad is like this
> select * from "nagios.CPULoad" limit 1
name: nagios.CPULoad
time hostname load1 load15 load5 state
---- -------- ----- ------ ----- -----
1487867813000000000 cbba.storage 0 0 0 OK
My URL to scripted.js is as follows:
http://10.72.6.220:3000/dashboard/script/scripted.js?name=CPULoad&field=load1&hostname=ussd3
name indicates the series in influxDB I want to graph
field indicates which field to use
hostname indicates the host to choose
The SQL I want grafana scripted.js to build is as follows
SELECT mean("load1") FROM "nagios.CPULoad" WHERE "hostname" = 'ussd3' AND $timeFilter GROUP BY time($interval) fill(null)
The code to build inside scripted.js involves modifying the "targets" parameter in dashboard.rows structure, and it turns out to be like this (i found this out after going through the code)
targets: [
{
"measurement": "nagios." + ARGS.name,
"metric": ARGS.name,
"tags": {
"hostname": {
operator: "=" ,
value: ARGS.hostname
}
},
"select": [[{
type: "field",
params: [ARGS.field]
}, {
type: "mean",
params: []
}]],
},
],
Now, I dont know why, but I had to modify the code in order for the key "hostname" to be taken into account. In function renderTagCondition which I copy here for convenience
a.prototype.renderTagCondition = function(a, b, c) {
var d = ""
, e = a.operator
, f = a.value;
return b > 0 && (d = (a.condition || "AND") + " "),
e || (e = /^\/.*\/$/.test(f) ? "=~" : "="),
"=~" !== e && "!~" !== e ? (c && (f = this.templateSrv.replace(f, this.scopedVars)),
">" !== e && "<" !== e && (f = "'" + f.replace(/\\/g, "\\\\") + "'")) : c && (f = this.templateSrv.replace(f, this.scopedVars, "regex")),
d + '"' + a.key + '" ' + e + " " + f
}
the returned value
d + '"' + a.key + '" ' + e + " " + f
seems to be wrong... It should be
d + '"' + b + '" ' + e + " " + f
since b carries "hostname"
After all this, calling the URL I mentioned at the beginning it all worked out pretty well
Adding to #mquevedob answer above,
Change the tags object like this
"tags":
[
{
key: "jobId",
operator: "=" ,
value: "340"
}
]
This should work fine in Grafana when using InfluxDB.

Inconsistent formatting of Go code?

Here are some example code:
func main() {
os.MkdirAll(outDir + id, 0755)
os.Create(outDir + id + "/txt")
os.OpenFile(outDir + id + "/" + ".tmp", os.OWRONLY|os_APPEND)
os.Stat(outDir + id + "/.tmp")
}
The following is the output after formatting with either go fmt or pressing Format on the Go Playground:
func main() {
os.MkdirAll(outDir+id, 0755)
os.Create(outDir + id + "/txt")
os.OpenFile(outDir+id+"/"+".tmp", os.OWRONLY|os_APPEND)
os.Stat(outDir + id + "/.tmp")
}
Spaces in os.MkdirAll() and os.OpenFile() are removed while they are untouched in os.Create() and os.Stat(). I would expect that formatting to be identical.
Why is this happening?
See: https://github.com/golang/go/issues/12720
gofmt uses spaces around binary expressions to express binding
strength. Depending on nesting level, spaces are removed.
You could also find these easily by searching for "gofmt inconsistent spaces".
See also issue #1206, #1848, #1861, #7880, and #11497.

Super simple download with progress bar

Setting up an asynchronous download in AutoHotkey is a pain, but this is is necessary if you want to run some code during the download, like for example updating progress bar.
So the question is:
Is there a short and simple way of downloading a file with a progress bar, without including huge 1000+ lines libraries?
I came up with that code quite some time ago and you can still find it on the AHK forums, however, why not share it with the Stackoverflow community:
DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True, ExpectedFileSize := 0) {
;Check if the file already exists and if we must not overwrite it
If (!Overwrite && FileExist(SaveFileAs))
Return
;Check if the user wants a progressbar
If (UseProgressBar) {
;Initialize the WinHttpRequest Object
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
;Download the headers
WebRequest.Open("HEAD", UrlToFile)
WebRequest.Send()
try {
;Store the header which holds the file size in a variable:
FinalSize := WebRequest.GetResponseHeader("Content-Length")
} catch e {
; Cannot get "Content-Length" header
FinalSize := ExpectedFileSize
}
;Create the progressbar and the timer
Progress, , , Downloading..., %UrlToFile%
LastSizeTick := 0
LastSize := 0
; Enable progress bar updating if the system knows file size
SetTimer, __UpdateProgressBar, 1500
}
;Download the file
UrlDownloadToFile, %UrlToFile%, %SaveFileAs%
;Remove the timer and the progressbar because the download has finished
If (UseProgressBar) {
Progress, Off
SetTimer, __UpdateProgressBar, Off
}
Return
;The label that updates the progressbar
__UpdateProgressBar:
;Get the current filesize and tick
CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results
CurrentSizeTick := A_TickCount
;Calculate the downloadspeed
SpeedOrig := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000))
SpeedUnit := "KB/s"
Speed := SpeedOrig
if (Speed > 1024) {
; Convert to megabytes
SpeedUnit := "MB/s"
Speed := Round(Speed/1024, 2)
}
SpeedText := Speed . " " . SpeedUnit
;Save the current filesize and tick for the next time
LastSizeTick := CurrentSizeTick
LastSize := FileOpen(SaveFileAs, "r").Length
if FinalSize = 0
{
PercentDone := 50
} else {
;Calculate percent done
PercentDone := Round(CurrentSize/FinalSize*100)
SpeedText := SpeedText . ", " . Round((FinalSize - CurrentSize) / SpeedOrig / 1024) . "s left"
}
;Update the ProgressBar
Progress, %PercentDone%, %PercentDone%`% (%SpeedText%), Downloading..., Downloading %SaveFileAs% (%PercentDone%`%)
Return
}
Here are some examples:
Example 1 - Download a firefox setup with a progressbar and overwrite it if it already exists on the disk:
DownloadFile("http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe", "firefox_setup.exe")
Example 2 - Download Autohotkey with a progressbar and don't overwrite it if it already exists:
Url = http://ahkscript.org/download/ahk-install.exe
DownloadAs = AutoHotkey_L Installer.exe
Overwrite := False
UseProgressBar := True
DownloadFile(Url, DownloadAs, Overwrite, UseProgressBar)
Example 3 - Download a CCleaner setup and open a Save As dialog, asking the user where to save the file, overwriting it if already exists:
FileSelectFile, SaveAs, S, ccsetup410.exe
DownloadFile("http://download.piriform.com/ccsetup410.exe", SaveAs, True, True)

Resources