英文:
How can i add methods to a struct in vlang?
问题
我对V语言相当陌生,但我了解您的问题。您想在Error结构体中创建一个方法来返回包含所有值的字符串,以便可以调用它并将其存储在变量中。以下是您尝试的两种方法:
方法1:创建一个函数并返回字符串
fn to_string(e Error) string {
return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}
方法2:将方法附加到结构体(不起作用)
fn (e Error) to_string() string {
return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}
您想让第二种方法起作用,但它在编译时产生错误,错误消息是:
structs/error.v:11:7: error: cannot define new methods on non-local type Error
根据错误消息,似乎V语言不允许在非局部类型Error上定义新方法。要解决这个问题,您可以考虑将to_string函数保留为结构体的外部函数,就像您在方法1中所做的那样。这是一个修订后的示例:
module structs
pub struct Error {
pub:
text string
row int
col int
complementary string
}
pub fn to_string(e Error) string {
return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}
然后,您可以在其他文件和模块中调用这个函数。
英文:
I am quite new to the v language and i discovered this feature, however it seems like i am doing something wrong.
I have a struct that gathers information in case an error is found somewhere and i'd like to create a function in the same structure to return a string containing all the values so that i can call it and store it in a variable the proper way: error_msg := error.to_string()
I am using v version 0.3.3
Having the Error struct:
pub struct Error {
pub:
text string
row int
col int
complementary string
}
I have tried:
- Creating a function and return it that way(This works but its not what i'd like)
fn to_string(e Error) string {
return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
- Appending a method to the struct(Not working)
fn (e Error) to_string() string {
return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
I would like the second option to work but it is outputing the following error while compiling it:
structs/error.v:11:7: error: cannot define new methods on non-local type Error
9 | }
10 |
11 | fn (e Error) to_string() string {
| ~~~~~
12 | return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
13 | }
The function and the struct are in the same module as expected and even in the same file
Full code
module structs
pub struct Error {
pub:
text string
row int
col int
complementary string
}
fn (e Error) to_string() string {
return e.text+'\n in row '+ e.row+' at col '+ e.col+'\n'+e.complementary
}
That being said, it is going to be called in another file and module:
pub fn read(file_name string) (int, string) {
data := read_file(file_name) or {
error_str := Error{text: 'File "$file_name" does not exist', row: 2, col: 0}
return 1, error_str.to_string()
}
return 0, data
}
答案1
得分: 0
错误信息“无法在非本地类型Error上定义新方法”是因为Error
是V内置的,因此已经在非本地定义了,您不能在此处添加新方法。
此外,您在方法定义上遇到此错误,可能是因为它在源代码中的结构定义之前。如果您交换它们的定义顺序(首先是结构,然后是方法),问题不会改变,但错误消息会更具针对性,会显示“无法注册结构Error
,已存在具有此名称的另一种类型”。
快速修复
给您的struct
一个新名称:
struct MyError {
text string
row int
col int
complementary string
}
fn (e MyError) to_string() string {
return e.text + '在行' + e.row.str() + '列' + e.col.str() + '\n' + e.complementary
}
error_str := MyError{text: '文件不存在', row: 2, col: 0}
println(error_str.to_string())
文件不存在
在行2列0
更符合惯用法的方法
定义适当的自定义错误类型,然后可以将其用作实际错误:要么手动实现IError
接口(需要两个方法msg() string
和code() int
),要么只嵌入接口的默认实现Error
(是的,您不小心尝试隐藏的那个),它提供了这两个方法的空副本,因此您只需添加需要的内容。例如:
struct MyError {
Error
text string
row int
col int
complementary string
}
fn (e MyError) msg() string {
return '${e.text}\n在行${e.row}列${e.col}\n${e.complementary}'
}
fn read(file_name string) !string {
failed := true
if failed {
return MyError{text: '文件"${file_name}"不存在', row: 2, col: 0}
}
return "数据"
}
data := read("xy") or { panic(err) }
println(data)
V panic: MyError: 文件"xy"不存在
在行2列0
v hash: 046dd54
/tmp/v_1000/main.13380111000873620315.tmp.c:7817: 在 _v_panic 中的回溯
/tmp/v_1000/main.13380111000873620315.tmp.c:17765: 由 main__main
/tmp/v_1000/main.13380111000873620315.tmp.c:18160: 由 main
英文:
The error cannot define new methods on non-local type Error
occurs because Error
is a V builtin, thus already defined (non-locally), and you cannot add a new method to that here.
Also, you're getting this error on the method definition because it presumably precedes the struct's definition in your source code. If you flipped their order of definition (struct first, then the method), the issue wouldn't change but the error message would have been more to the point, reading: cannot register struct `Error`, another type with this name exists
.
The quick fix
Give your struct
a new name:
struct MyError {
text string
row int
col int
complementary string
}
fn (e MyError) to_string() string {
return e.text + '\n in row ' + e.row.str() + ' at col ' + e.col.str() + '\n' + e.complementary
}
error_str := MyError{text: 'File does not exist', row: 2, col: 0}
println(error_str.to_string())
File does not exist
in row 2 at col 0
A more idiomatic approach
Define proper custom error types which you can then use as actual errors: Either manually implement the IError
interface (requiring the two methods msg() string
and code() int
), or just embed the interface's default implementation Error
(yes, the one you have accidentally been trying to shadow) which provides empty copies of both methods, so you only have to add what's needed. For instance:
struct MyError {
Error
text string
row int
col int
complementary string
}
fn (e MyError) msg() string {
return '${e.text}\n in row ${e.row} at col ${e.col}\n${e.complementary}'
}
fn read(file_name string) !string {
failed := true
if failed {
return MyError{text: 'File "${file_name}" does not exist', row: 2, col: 0}
}
return "data"
}
data := read("xy") or { panic(err) }
println(data)
V panic: MyError: File "xy" does not exist
in row 2 at col 0
v hash: 046dd54
/tmp/v_1000/main.13380111000873620315.tmp.c:7817: at _v_panic: Backtrace
/tmp/v_1000/main.13380111000873620315.tmp.c:17765: by main__main
/tmp/v_1000/main.13380111000873620315.tmp.c:18160: by main
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论