I'm trying to understand golang interface, my problem is that why err2.What undefined.
Here is a simple code. The output indicates that both err and err2 have same type as *main.MyError, but err2 have no field "What", so there must be some difference between err and err2, but I cannot figure out the difference here. I just began learning golang not long before, any help will be greatly appreciated.
package main
import (
"fmt"
"time"
"reflect"
)
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
err := &MyError{time.Now(), "Hello"}
fmt.Println(reflect.TypeOf(err))
fmt.Println(err.What)
err2 := run()
fmt.Println(reflect.TypeOf(err2))
fmt.Println(err2.What)
}
expected output:
main.MyError
Hello
main.MyError
it didn't work
actual output:
\# command-line-arguments
./test.go:34:18: err2.What undefined (type error has no field or method What)
The function run() returns a value of type error, which is an interface type. Yes, it wraps a value of concrete type *MyError, but to get access to MyError's fields, you need to use a type assertion:
fmt.Println(err2.(*MyError).What)
Try it on the Go Playground.
Note that a value of error type may contain values of other concrete types, actually any that implements the error interface. If it would contain a value of another type, the above type assertion would result in a runtime panic.
If you're unsure err2 actually holds a value of type *MyError and you want to avoid the runtime panic, you may use the special form of type assertion to get this information and only act if it is so:
if myerror, ok := err2.(*MyError); ok {
fmt.Println(myerror.What) // Here myerror has static type *MyError
} else {
fmt.Println("Some other error:", err2)
}
Try this one on the Go Playground.
I think the interface of error type is let you use Error() method without any detail in the concrete structure. You can check on the Go Playground
Related
I am trying to capture the content displayed in a webview (not the source, which is a bunch of javascripts). I'm hoping wkwebview's createWebArchiveData is the right method.
So, where I am getting confused is what gets returned from the call.
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.createWebArchiveData(completionHandler: { (result) in
})
the docs say result is Result<data, error>. I did a type(of:) on it and the log printed Result<data, error>...thanks Apple...
when I printed result I got:
success(5990802 bytes)
thought maybe it was a tuple, but result.0 threw an error...
Value of type 'Result<Data, Error>' has no member '0'
tried to convert data to string...that didn't work...
tried to unarchive it, that failed as well.
Cannot convert value of type 'Result<Data, Error>' to expected argument type 'Data
so, any help would be appreciated. I need what is displayed on the screen, not the source code (in case I am going about this wrong).
I solved this. The Result object is an enum with two cases success and failure. You would read the value (in this case because it is Data) like so:
webView.createWebArchiveData(completionHandler: { (result) in
//var strResult = String(utf8String: result)
switch result {
case .success(let data):
let str = String(decoding: data, as: UTF8.self)
print(str)
case .failure(let error):
print(error)
}
})
You have get() method that will return data if result is success, less code for sure :)
if let data = try? result.get() {
//do something with data
}
I forked this project, so I am not as familiar with all of the details: https://github.com/nebs/hello-bluetooth/blob/master/HelloBluetooth/NSData%2BInt8.swift.
This is all part of an extension of NSData that the I am using to send 8-bit values to an Arduino.
func int8Value() -> Int8 {
var value: Int8 = 0
copyBytes(to: &UInt8(value), count: MemoryLayout<Int8>.size) //BUG
return value
}
However, it appears in Swift 3 that this now throws an error in the copyBytes section. Although I have seen some solutions such as passing an address in the parameter, I did not want to risk breaking the remaining parts of the code. Any suggestions on what to do for this?
The original code was incorrect. UInt8(value) generates a new, immutable value which you cannot write to. I assume the old compiler just let you get away with it, but it was never correct.
What they meant to do was to write to the expected type, and then convert the type at the end.
extension Data {
func int8Value() -> Int8 {
var value: UInt8 = 0
copyBytes(to: &value, count: MemoryLayout<UInt8>.size)
return Int8(value)
}
}
That said, I wouldn't do it that way today. Data will coerce its values to whatever type you want automatically, so this way is safer and simpler and very general:
extension Data {
func int8ValueOfFirstByte() -> Int8 {
return withUnsafeBytes{ return $0.pointee }
}
}
Or this way, which is specific to ints (and even simpler):
extension Data {
func int8Value() -> Int8 {
return Int8(bitPattern: self[0])
}
}
I am very new to rust and trying to write a command line utility as a way to learn.
I am getting the list of args and trying to match on them
let args = os::args()
//some more code
match args[1].into_ascii_lower().as_slice() {
"?" | "help" => { //show help },
"add" => { //do other stuff },
_ => { //do default stuff }
}
this causes this error
cannot move out of dereference (dereference is implicit, due to indexing)
match args[1].into_ascii_lower().as_slice() {
^~~~~~~
I have no idea what that means, but searching yield this which I didn't completely get, but changing the args[1] to args.get(1) gives me another error
error: cannot move out of dereference of `&`-pointer
match args.get(1).into_ascii_lower().as_slice() {
^~~~~~~~~~~
what's going on?
As you can see in the documentation, the type of into_ascii_lower() is (see here) :
fn into_ascii_upper(self) -> Self;
It takes self directly, not as a reference. Meaning it actually consumes the String and return an other one.
So, when you do args[1].into_ascii_lower(), you try to directly consume one of the elements of args, which is forbidden. You probably want to make a copy of this string, and call into_ascii_lower() on this copy, like this :
match args[1].clone().into_ascii_lower().as_slice() {
/* ... */
}
This questions follows another question of mine.
I don't exactly get what is wrong with my attempt to convert res to a ListSociete in the following test code :
import (
"errors"
"fmt"
"github.com/jmcvetta/neoism"
)
type Societe struct {
Name string
}
type ListSociete []Societe
func loadListSociete(name string) (ListSociete, error) {
db, err := neoism.Connect("http://localhost:7474/db/data")
if err != nil {
return nil, err
}
res := []struct {
Name string `json:"a.name"`
}{}
cq := neoism.CypherQuery{
Statement: `
MATCH (a:Societe)
WHERE a.name = {name}
RETURN a.name
`,
Parameters: neoism.Props{"name": name},
Result: &res,
}
db.Cypher(&cq)
if len(res) == 0 {
return nil, errors.New("Page duz not exists")
}
r := res[0]
return ListSociete(res), nil
}
Is a []struct{Name string} different from a []struct{Name string json:"a.name" } ?
Or is a ListSociete different from a []struct{Name string} ?
Thanks.
You are currently dealing with two different types:
type Societe struct {
Name string
}
and the anonymous one:
struct {
Name string `json:"a.name"`
}
These two would be identical if it wasn't for the tag. The Go Specifications states (my emphasis):
Two struct types are identical if they have the same sequence of fields, and if
corresponding fields have the same names, and identical types, and identical tags.
Two anonymous fields are considered to have the same name. Lower-case field names
from different packages are always different.
So, you can't do a simple conversion between the two. Also, the fact that you are converting slices of the two types makes the conversion problematic. I can see two options for you:
Copy through iteration:
This is the safe and recommended solution, but it is also more verbose and slow.
ls := make(ListSociete, len(res))
for i := 0; i < len(res); i++ {
ls[i].Name = res[i].Name
}
return ls, nil
Unsafe conversion:
Since both types have the same underlying data structure, it is possible to do an unsafe conversion.
This might however blow up in your face later on. Be warned!
return *(*ListSociete)(unsafe.Pointer(&res)), nil
Playground Example: http://play.golang.org/p/lfk7qBp2Gb
So, after some tests, here's whats i found out :
A ListSociete defined as such...
type Societe struct {
Name string `json:"a.name"`
}
type ListSociete []Societe
is different from this :
type ListSociete []struct {
Name string `json:"a.name"`
}
This second solution works, whereas the first doesn't.
So I assume there really is no way to convert (directly without writing an explicit loop) between types with different tags ?
In that case, i'll definitely go with the loop, as using tags directly in types (cf. second solution above) would make my code unreadable and unreusable, also I really have no clue what I would be messing with using the unsafe conversion method. So thanks for confirming different tags made different types.
I'm getting the above error, but as far as I can tell I've matched my argument list exactly.
Code:
void lorentzTransform(std::list<point2P1D>& vol, const vector2D& v) {
std::list<point2P1D> temp = std::list<point2P1D>();
for (const point2P1D& pt : vol) {
point2P1D test = lorentzTransform(pt, v); //Error here.
temp.push_back(test);
}
vol.swap(temp);
}
point2P1D lorentzTransform(const point2P1D& pt, const vector2D& vel);
The overload you want to call might not actually visible of the point of calling. The prototype you show must be placed above the other function.
I'm also very worried about that reference return type. I consider it very likely that you return a dangling reference there.