I have specific questions for my project
input = "3d6"
I want to convert this string some parts to integer. For instance I want to use input[0] like integer.
How can I do this?
There's two problems here:
How to convert a string to an integer
The most straightforward method is the Atoi (ASCII to integer) function in the strconv package., which will take a string of numeric characters and coerce them into an integer for you.
How to extract meaningful components of a known string pattern
In order to use strconv.Atoi, we need the numeric characters of the input by themselves. There's lots of ways to slice and dice a string.
You can just grab the first and last characters directly - input[:1] and input[2:] are the ticket.
You could split the string into two strings on the character "d". Look at the split method, a member of the strings package.
For more complex problems in this space, regular expressions are used. They're a way to define a pattern the computer can look for. For example, the regular expression ^x(\d+)$ will match on any string that starts with the character x and is followed by one or more numeric characters. It will provide direct access to the numeric characters it found by themselves.
Go has first class support for regular expressions via its regexp package.
For example,
package main
import (
"fmt"
)
func main() {
input := "3d6"
i := int(input[0] - '0')
fmt.Println(i)
}
Playground: https://play.golang.org/p/061miKcXdIF
Output:
3
Coming from Python, I'm not used to see code lines longer than 80 columns.
So when I encounter this:
err := database.QueryRow("select * from users where user_id=?", id).Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)
I tried to break it to
err := database.QueryRow("select * from users where user_id=?", id) \
.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)
But I get
syntax error: unexpected \
I also tried just breaking the line with hitting enter and put a semicolon at the end:
err := database.QueryRow("select * from users where user_id=?", id)
.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email);
But the I again get:
syntax error: unexpected .
So I'm wondering what's the golangic way to do so?
First some background. The formal grammar of Go uses semicolons ";" as terminators in many productions, but Go programs may omit most of them (and they should to have a clearer, easily readable source; gofmt also removes unnecessary semicolons).
The specification lists the exact rules. Spec: Semicolons:
The formal grammar uses semicolons ";" as terminators in a number of productions. Go programs may omit most of these semicolons using the following two rules:
When the input is broken into tokens, a semicolon is automatically inserted into the token stream immediately after a line's final token if that token is
an identifier
an integer, floating-point, imaginary, rune, or string literal
one of the keywords break, continue, fallthrough, or return
one of the operators and delimiters ++, --, ), ], or }
To allow complex statements to occupy a single line, a semicolon may be omitted before a closing ")" or "}".
So as you can see if you insert a newline character after the parenthesis ), a semicolon ; will be inserted automatically and so the next line will not be treated as the continuation of the previous line. This is what happened in your case, and so the next line starting with .Scan(&ReadUser.ID,... will give you a compile-time error as this standing by itself (without the previous line) is a compile-time error: syntax error: unexpected .
So you may break your line at any point which does not conflict with the rules listed under point 1. above.
Typically you can break your lines after comma ,, after opening parenthesis e.g. (, [, {, and after a dot . which may be referencing a field or method of some value. You can also break your line after binary operators (those that require 2 operands), e.g.:
i := 1 +
2
fmt.Println(i) // Prints 3
One thing worth noting here is that if you have a struct or slice or map literal listing the initial values, and you want to break line after listing the last value, you have to put a mandatory comma , even though this is the last value and no more will follow, e.g.:
s := []int {
1, 2, 3,
4, 5, 6, // Note it ends with a comma
}
This is to conform with the semicolon rules, and also so that you can rearrange and add new lines without having to take care of adding / removing the final comma; e.g. you can simply swap the 2 lines without having to remove and to add a new comma:
s := []int {
4, 5, 6,
1, 2, 3,
}
The same applies when listing arguments to a function call:
fmt.Println("first",
"second",
"third", // Note it ends with a comma
)
The simplest way is to simply leave the operator (.) on the first line.
\ line continuations are also discouraged in many python style guides, you could wrap the whole expression in parens if you are moving back and forth between go and python as this technique works in both languages.
As mentioned, this is a matter of style preference. I understand that the creators of Go have suggested a style based on their experience of which I learn from but also keep some of my own style from my experience.
Below is how I would format this:
err := database.
QueryRow("select * from users where user_id=?", id).
Scan(
&ReadUser.ID,
&ReadUser.Name,
&ReadUser.First,
&ReadUser.Last,
&ReadUser.Email,
)
It's a matter of style, but I like:
err := database.QueryRow(
"select * from users where user_id=?", id,
).Scan(
&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email,
)
what's the golangic way to do so?
An automated solution. Unfortunately, gofmt doesn't cover this case so you could use
https://github.com/segmentio/golines
Install it via
go install github.com/segmentio/golines#latest
Then run
golines -w -m 80 .
-w means make the changes in-place (default prints to stdout)
-m is max column length
You can break the line at several places like commas or braces as suggested by other answers. But Go community has this opinion on line length:
There is no fixed line length for Go source code. If a line feels too long, it should be refactored instead of broken.
There are several guidelines there in the styling guide. I am adding some of the notable ones (clipped):
Commentary
Ensure that commentary is readable from source even on narrow screens.
...
When possible, aim for comments that will read well on an 80-column wide terminal, however this is not a hard cut-off; there is no fixed line length limit for comments in Go.
Indentation confusion
Avoid introducing a line break if it would align the rest of the line with an indented code block. If this is unavoidable, leave a space to separate the code in the block from the wrapped line.
// Bad:
if longCondition1 && longCondition2 &&
// Conditions 3 and 4 have the same indentation as the code within the if.
longCondition3 && longCondition4 {
log.Info("all conditions met")
}
Function formatting
The signature of a function or method declaration should remain on a single line to avoid indentation confusion.
Function argument lists can make some of the longest lines in a Go source file. However, they precede a change in indentation, and therefore it is difficult to break the line in a way that does not make subsequent lines look like part of the function body in a confusing way:
// Bad:
func (r *SomeType) SomeLongFunctionName(foo1, foo2, foo3 string,
foo4, foo5, foo6 int) {
foo7 := bar(foo1)
// ...
}
// Good:
good := foo.Call(long, CallOptions{
Names: list,
Of: of,
The: parameters,
Func: all,
Args: on,
Now: separate,
Visible: lines,
})
// Bad:
bad := foo.Call(
long,
list,
of,
parameters,
all,
on,
separate,
lines,
)
Lines can often be shortened by factoring out local variables.
// Good:
local := helper(some, parameters, here)
good := foo.Call(list, of, parameters, local)
Similarly, function and method calls should not be separated based solely on line length.
// Good:
good := foo.Call(long, list, of, parameters, all, on, one, line)
// Bad:
bad := foo.Call(long, list, of, parameters,
with, arbitrary, line, breaks)
Conditionals and loops
An if statement should not be line broken; multi-line if clauses can lead to indentation confusion.
// Bad:
// The second if statement is aligned with the code within the if block, causing
// indentation confusion.
if db.CurrentStatusIs(db.InTransaction) &&
db.ValuesEqual(db.TransactionKey(), row.Key()) {
return db.Errorf(db.TransactionError, "query failed: row (%v): key does not match transaction key", row)
}
If the short-circuit behavior is not required, the boolean operands can be extracted directly:
// Good:
inTransaction := db.CurrentStatusIs(db.InTransaction)
keysMatch := db.ValuesEqual(db.TransactionKey(), row.Key())
if inTransaction && keysMatch {
return db.Error(db.TransactionError, "query failed: row (%v): key does not match transaction key", row)
}
There may also be other locals that can be extracted, especially if the conditional is already repetitive:
// Good:
uid := user.GetUniqueUserID()
if db.UserIsAdmin(uid) || db.UserHasPermission(uid, perms.ViewServerConfig) || db.UserHasPermission(uid, perms.CreateGroup) {
// ...
}
// Bad:
if db.UserIsAdmin(user.GetUniqueUserID()) || db.UserHasPermission(user.GetUniqueUserID(), perms.ViewServerConfig) || db.UserHasPermission(user.GetUniqueUserID(), perms.CreateGroup) {
// ...
}
switch and case statements should also remain on a single line.
// Good:
switch good := db.TransactionStatus(); good {
case db.TransactionStarting, db.TransactionActive, db.TransactionWaiting:
// ...
case db.TransactionCommitted, db.NoTransaction:
// ...
default:
// ...
}
// Bad:
switch bad := db.TransactionStatus(); bad {
case db.TransactionStarting,
db.TransactionActive,
db.TransactionWaiting:
// ...
case db.TransactionCommitted,
db.NoTransaction:
// ...
default:
// ...
}
If the line is excessively long, indent all cases and separate them with a blank line to avoid indentation confusion:
// Good:
switch db.TransactionStatus() {
case
db.TransactionStarting,
db.TransactionActive,
db.TransactionWaiting,
db.TransactionCommitted:
// ...
case db.NoTransaction:
// ...
default:
// ...
}
Never brake long URLs into multiple lines.
I have only added some of the few examples there are in the styling guide. Please read the guide to get more information.
There many cases in Rust when a block of code can end with or without comma.
For example:
enum WithoutComma
{
x,
y
}
or
enum WithComma
{
x,
y,
}
There are also other examples with match, etc. It seems that both variants lead to the same result. The only case I know where adding or removing a comma changes behaviour is the 1-element tuple declaration (which isn't a block):
let just_int = (5);
let tuple = (5,);
Why can one use a comma or not at the end of a block? Why is there such dualism in thelanguage and what are the reasons for it?
As you say, the only time a trailing comma is required is the 1-tuple pattern, type and construction let (x,): (Type,) = (1,). Everywhere else, trailing commas are optional, have no effect, but are allowed for a few reasons:
it makes macros easier: no need to be careful to not insert a comma at the very end of a sequence of items.
it makes diffs nicer when extending a list of things, e.g. adding a variant to
enum Foo {
Bar
}
gives
enum Foo {
Bar,
Baz
}
which is changing two lines (i.e. tools like git will display the Bar line as modified, as well as the inserted line), even though only the second actually had anything interesting in the change. If Bar started out with a trailing comma, then inserting Baz, after it is fine, with only one line changed.
They're not required (other than the 1-tuple) because that would be fairly strange (IMO), e.g.
fn foo(x: u16,) -> (u8, u8,) {
(bar(x,), baz(x,),)
}
(I guess it would look less strange for enum/struct declarations, but still, it's nice to be able to omit it.)
In my experience, it's common to see spaces put inside braces for one-line definitions, e.g. this function in JavaScript:
function(a, b) { return a * b; }
Is there any technical/historical reason that most programmers seem to do this, particularly given that spaces are not included inside parentheses?
Besides readability, in some languages, such as Verilog, identifiers can be escaped (by a \ at their beginning) so that they use special characters in their names. For example, the following names are legal identifier names in Verilog:
q
\q~ //escaped version which uses ~ in the name
\element[32] //a single variable (not part of an array) whose name is \element[32]
Such identifiers, should always terminate by space, otherwise the character after them would be considered as the identifier's name:
{ d, \q~ } // Concatenating d and \q~ in a vector
{ d, \q~} // Concatenating d and \q~} in a vector. Will generate a missing brace error.
Spaces are mostly used for readability. Most of the coding styles will tell you to judiciously use whitespace in your code to make it more readable.
As an example, look at this statement: *a = *b + *c;. Think how it will seem without the whitespace.
I'm trying to scan through a JavaScript document that has many functions defined throughout it, and to delete a function from the document. I'm hoping that there's a trivial regex trick that I can do here.
Example:
Some JavaScript document:
function wanted_foo(bar) {
...
...
}
function unwanted_foo(bar) {
...
inner_foo {
...
...
}
}
function wanted_foo(bar) {
...
...
inner_foo {
...
...
}
}
The obvious problem here is that I need to match things of the form "function unwanted_foo(bar) { ... }", except that I only need to match up until the last curly brace of the function, and not to the next curly brace of another function. Is there a simple Regex way of doing this?
Normal regular expressions can't do this because they can't keep count of the previously matched braces and therefore can't find the last one, nonetheless it seems many implementations have capabilities that go beyond normal regex's and Ruby is one of those cases.
Hare are a couple of references about that, although it might not be what you would call simple.
Matching braces in ruby with a character in front
Backreferences
One "trick" is to use a counter together with regex.
Initialize your counter to 0
Match something of the form /^\s*function\s+\w+\(.*\)\s*\{ and when you have found this pattern, remember the position.
When you match that pattern, increment your counter
Now match { and } separately and increment or decrement your counter depending on what you've found.
Keep doing this until your counter is 0 again, then you should have found a function
Hope that's useful to you?