Complex conditional statement in golang - if-statement

I recently started learning golang and Revel. Im trying to understand what exactly the below if statement does. Seems like it is doing a type check, but i dont see what the conditional achieves. Appreciate if anyone can tell me whats happening here. thanks
if str, ok := obj.(string); ok {
return len(str) > 0
}

It tries to convert obj (which is of some abstract interface probably) into a string, checks if that worked, and only enters if it turned out okay.
Written more sparsely it can be viewed as:
// do a type assertion/conversion of obj to a string.
// If obj isn't really a string, ok will be false
str, ok := obj.(string)
// this will only run if we're talking about a string
if ok {
return len(str) > 0
}
What go does is safe casting from some interface to the real type. If you do this without the ok part, your program will panic if obj isn't a string. i.e this code will crash your program if obj isn't a string:
str := obj.(string)
return len(str) > 0
You can read more about type assertions in the docs:
http://golang.org/ref/spec#Type_assertions

This is called a type assertion. Your variable obj is an interface{}, in other words, its real type can change from one execution to another. A type assertion is used to determine the real type of an interface{}. There are two ways to do so:
str = obj.(string)
This one is unsecure: if ever obj is not a string, the program will panic. The other one is the one you used in your code. If obj is not a string, the ok boolean will be false.
For instance:
func f(v interface{}) {
if _, ok := v.(string); ok {
fmt.Println("v is a string!")
} else if _, ok := v.(float64); ok {
fmt.Println("v is a float64!")
} else {
fmt.Println("v is something else...")
}
}
f(17.42) // "v is a float64!"
f("foobar") // "v is a string!"
f([]string{"hello", "world"}) // "v is something else..."

Related

Get Error Complex object error after check isStruct or isSimpleValue

I have a code to display message if upload process fails. The message variable can be a struct or a string. I've added code to check if the result is a struct or a simple value but I still get Complex object error. Is there anything that I missed?
Here is my code:
if (isStruct(result)) {
if(StructKeyExists(result, 'messages')){
theMessage = result.messages;
}
}else{
if(IsSimpleValue(result)){
theMessage = result;
}
}
FormMessage=getLang('CVLizerUploadFailed') & ' ' & getLang('PleaseContactYourAdmin') & ', ' & getLang('ErrorCode') & ' ' & theMessage;
First let's simplify your code like below. It can be simplified further depending upon the earlier code, you need to look for it. The below code will check the type of result variable and depending upon type, it will set the value of theMessage variable.
if (isStruct(result) AND StructKeyExists(result, 'messages')) {
theMessage = result.messages;
}
else if (isSimpleValue(result){
theMessage = result;
}
There is nothing wrong with the code you wrote or simplified code. I can not say for sure that if there is wrong with last line of code as i do not have enough information on it.
Use writedump and abort immediately below and above the if condition code block in both cases when result is a struct and a variable to check when error occures. It's either the last line or any other line of code above this block of code.

reader.ReadString does not strip out the first occurrence of delim

I wrote a simple go program and it isn't working as it should:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Who are you? \n Enter your name: ")
text, _ := reader.ReadString('\n')
if aliceOrBob(text) {
fmt.Printf("Hello, ", text)
} else {
fmt.Printf("You're not allowed in here! Get OUT!!")
}
}
func aliceOrBob(text string) bool {
if text == "Alice" {
return true
} else if text == "Bob" {
return true
} else {
return false
}
}
It should ask the user to tell it's name and, if he is either Alice or Bob, greet him and else tell him to get out.
The problem is, that even when the entered name is Alice or Bob, it tells the User to get out.
Alice:
/usr/lib/golang/bin/go run /home/jcgruenhage/go/workspace/src/github.com/jcgruenhage/helloworld/greet/greet.go
Who are you?
Enter your name: Alice
You're not allowed in here! Get OUT!!
Process finished with exit code 0
Bob:
/usr/lib/golang/bin/go run /home/jcgruenhage/go/workspace/src/github.com/jcgruenhage/helloworld/greet/greet.go
Who are you?
Enter your name: Bob
You're not allowed in here! Get OUT!!
Process finished with exit code 0
This is because your the text is storing Bob\n
One way to solve this is using strings.TrimSpace to trim the newline, eg:
import (
....
"strings"
....
)
...
if aliceOrBob(strings.TrimSpace(text)) {
...
Alternatively, you can also use ReadLine instead of ReadString, eg:
...
text, _, _ := reader.ReadLine()
if aliceOrBob(string(text)) {
...
The reason why the string(text) is needed is because ReadLine will return you byte[] instead of string.
I think the source of confusion here is that:
text, _ := reader.ReadString('\n')
Does not strip out the \n, but instead keeps it as last value, and ignores everything after it.
ReadString reads until the first occurrence of delim in the input,
returning a string containing the data up to and including the
delimiter.
https://golang.org/src/bufio/bufio.go?s=11657:11721#L435
And then you end up comparing Alice and Alice\n. So the solution is to either use Alice\n in your aliceOrBob function, or read the input differently, as pointed out by #ch33hau.
I don't know anything about Go, but you might want to strip the string of leading or trailing spaces and other whitespace (tabs, newline, etc) characters.
reader.ReadLine()
Can leave ā€˜\nā€™ but reader.ReadString() can't

vector subscript out of range C++ (substring)

So I'm having this problem with substrings and converting them into integers. This will probably be an easy-fix but I'm not managing to find the answer.
So I receive this string "12-12-2012" and i want to split it, convert into integers and call the modifications methods like this:
string d = (data.substr(0,data.find("-")));
setDia(atoi(d.c_str()));
But it gives me the error mentioned in the title when I try to comvert into an integer.
EDIT:
Turns out that the string doesn't actually contain a '-' but this is really confusing since the string in the parameter results from this : to_char(s.diaInicio,'dd-mm-yyyy')
More information: I used the debugger and it's making the split correctly since the value that atoi receives is 12 (the first split). But I don't know why the VS can't convert into an integer even though the string passed is "12".
This code is not save in the sense that it fails when data does not contain a -.
Try this:
std::size_t p = data.find("-");
if(p == std::string::npos) {
// ERROR no - in string!
}
else {
std::string d = data.substr(0,p);
setDia(atoi(d.c_str()));
}
Please duplicate the problem with a very simple program. If what you say is correct, then the following program should also fail (taken from Danvil's example, and without calling the unknown (to us) setDia() function):
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
string data = "12-12-2012";
std::size_t p = data.find("-");
if(p == std::string::npos) {
// ERROR no - in string!
}
else {
std::string d = data.substr(0,p);
atoi(d.c_str());
}
}

string.search(".") always return 0

I am work in Flash Builder 4.
Create e-mail validator on Flex.
Have this code
public var s:String="";
public function checkSumbols(_s:String=""):Boolean {
s=_s; //e-mail address (input mail#supermail.com)
var hDog:int=0;
var hPoint:int=0;
//check #
hDog=s.search("#");
trace(hDog) // It's work
if(hDog==-1) {
return false;
} else {
hPoint=s.substr(hDog).search(".");
trace(hPoint); // PANIC this return always 0
if(hPoint==-1){
return false;
}}
}
You could use regex. Since dot (.) has special meaning in regex you need to put 'escape' character before: yourString.search(/\./);
Should work.
HTH
FTQuest
search() accepts a pattern, and . just means "a single character", so it is probably returning the first single character, which would most likely be at index 0.
You could try search("\.")
I try with search(/[.]/) and it worked well in javascript, I think that It would work in the same mode in as3

Regex Rejecting matches because of Instr

What's the easiest way to do an "instring" type function with a regex? For example, how could I reject a whole string because of the presence of a single character such as :? For example:
this - okay
there:is - not okay because of :
More practically, how can I match the following string:
//foo/bar/baz[1]/ns:foo2/#attr/text()
For any node test on the xpath that doesn't include a namespace?
(/)?(/)([^:/]+)
Will match the node tests but includes the namespace prefix which makes it faulty.
I'm still not sure whether you just wanted to detect if the Xpath contains a namespace, or whether you want to remove the references to the namespace. So here's some sample code (in C#) that does both.
class Program
{
static void Main(string[] args)
{
string withNamespace = #"//foo/ns2:bar/baz[1]/ns:foo2/#attr/text()";
string withoutNamespace = #"//foo/bar/baz[1]/foo2/#attr/text()";
ShowStuff(withNamespace);
ShowStuff(withoutNamespace);
}
static void ShowStuff(string input)
{
Console.WriteLine("'{0}' does {1}contain namespaces", input, ContainsNamespace(input) ? "" : "not ");
Console.WriteLine("'{0}' without namespaces is '{1}'", input, StripNamespaces(input));
}
static bool ContainsNamespace(string input)
{
// a namspace must start with a character, but can have characters and numbers
// from that point on.
return Regex.IsMatch(input, #"/?\w[\w\d]+:\w[\w\d]+/?");
}
static string StripNamespaces(string input)
{
return Regex.Replace(input, #"(/?)\w[\w\d]+:(\w[\w\d]+)(/?)", "$1$2$3");
}
}
Hope that helps! Good luck.
Match on :? I think the question isn't clear enough, because the answer is so obvious:
if(Regex.Match(":", input)) // reject
You might want \w which is a "word" character. From javadocs, it is defined as [a-zA-Z_0-9], so if you don't want underscores either, that may not work....
I dont know regex syntax very well but could you not do:
[any alpha numeric]\*:[any alphanumeric]\*
I think something like that should work no?
Yeah, my question was not very clear. Here's a solution but rather than a single pass with a regex, I use a split and perform iteration. It works as well but isn't as elegant:
string xpath = "//foo/bar/baz[1]/ns:foo2/#attr/text()";
string[] nodetests = xpath.Split( new char[] { '/' } );
for (int i = 0; i < nodetests.Length; i++)
{
if (nodetests[i].Length > 0 && Regex.IsMatch( nodetests[i], #"^(\w|\[|\])+$" ))
{
// does not have a ":", we can manipulate it.
}
}
xpath = String.Join( "/", nodetests );