<?xml version="1.0" encoding="utf-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Форум программистов и сисадминов Киберфорум - Блоги - DrType</title>
		<link>https://www.cyberforum.ru/blogs/1501512/</link>
		<description>КиберФорум - форум программистов, системных администраторов, администраторов баз данных, компьютерный форум, форум по электронике и бытовой технике, обсуждение софта. Бесплатная помощь в решении задач по программированию и наукам, решение проблем с компьютером, операционными системам</description>
		<language>ru</language>
		<lastBuildDate>Fri, 11 Sep 2026 09:01:42 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.cyberforum.ru//cyberstatic.net/images/misc/rss.jpg</url>
			<title>Форум программистов и сисадминов Киберфорум - Блоги - DrType</title>
			<link>https://www.cyberforum.ru/blogs/1501512/</link>
		</image>
		<item>
			<title>Написание кастомного правила для go-playground/validator</title>
			<link>https://www.cyberforum.ru/blogs/1501512/8381.html</link>
			<pubDate>Thu, 04 Jan 2024 11:14:54 GMT</pubDate>
			<description>Юзаю пакет github.com/go-playground/validator/v10...</description>
			<content:encoded><![CDATA[<div>Юзаю пакет <a rel="nofollow noopener noreferrer" href="https://pkg.go.dev/github.com/go-playground/validator/v10" target="_blank" title="https://pkg.go.dev/github.com/go-playground/validator/v10">github.com/go-playground/validator/v10</a> для валидации запросов в Fiber (в пет-прожекте).<br />
Захотелось иметь правило валидации наподобие ларавелевского <a rel="nofollow noopener noreferrer" href="https://laravel.com/docs/10.x/validation#rule-exists" target="_blank" title="https://laravel.com/docs/10.x/validation#rule-exists">exists</a>. Реализовал следующим образом:<br />
<div class="codeblock"><table class="go"><thead><tr><td colspan="2" id="978053484"  class="head">Go</td></tr></thead><tbody><tr class="li1"><td><div id="978053484" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="de1"><pre class="de1"><span class="kw1">package</span> validators
&nbsp;
<span class="kw1">import</span> <span class="sy1">(</span>
&nbsp; &nbsp; <span class="st0">&quot;my-project/db&quot;</span>
&nbsp; &nbsp; <span class="st0">&quot;fmt&quot;</span>
&nbsp; &nbsp; <span class="st0">&quot;reflect&quot;</span>
&nbsp; &nbsp; <span class="st0">&quot;strings&quot;</span>
&nbsp;
&nbsp; &nbsp; <span class="st0">&quot;github.com/go-playground/validator/v10&quot;</span>
<span class="sy1">)</span>
&nbsp;
<span class="kw4">func</span> Exists<span class="sy1">(</span>fl validator<span class="sy3">.</span>FieldLevel<span class="sy1">)</span> <span class="kw4">bool</span> <span class="sy1">{</span>
&nbsp; &nbsp; params <span class="sy2">:=</span> strings<span class="sy3">.</span>Split<span class="sy1">(</span>fl<span class="sy3">.</span>Param<span class="sy1">(),</span> <span class="st0">&quot;.&quot;</span><span class="sy1">)</span>
&nbsp; &nbsp; table <span class="sy2">:=</span> params<span class="sy1">[</span><span class="nu0">0</span><span class="sy1">]</span>
&nbsp; &nbsp; column <span class="sy2">:=</span> <span class="st0">&quot;id&quot;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw3">len</span><span class="sy1">(</span>params<span class="sy1">)</span> &gt; <span class="nu0">1</span> <span class="sy1">{</span>
&nbsp; &nbsp; &nbsp; &nbsp; column <span class="sy2">=</span> params<span class="sy1">[</span><span class="nu0">1</span><span class="sy1">]</span>
&nbsp; &nbsp; <span class="sy1">}</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">var</span> value any
&nbsp; &nbsp; <span class="kw1">switch</span> valueType <span class="sy2">:=</span> fl<span class="sy3">.</span>Field<span class="sy1">()</span><span class="sy3">.</span>Kind<span class="sy1">();</span> valueType <span class="sy1">{</span>
&nbsp; &nbsp; <span class="kw1">case</span> reflect<span class="sy3">.</span>String<span class="sy1">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; value <span class="sy2">=</span> fl<span class="sy3">.</span>Field<span class="sy1">()</span><span class="sy3">.</span>String<span class="sy1">()</span>
&nbsp; &nbsp; <span class="kw1">case</span> reflect<span class="sy3">.</span>Int<span class="sy1">:</span>
&nbsp; &nbsp; &nbsp; &nbsp; value <span class="sy2">=</span> fl<span class="sy3">.</span>Field<span class="sy1">()</span><span class="sy3">.</span>Int<span class="sy1">()</span>
&nbsp; &nbsp; <span class="sy1">}</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">var</span> result <span class="kw4">int</span>
&nbsp; &nbsp; db<span class="sy3">.</span>Database<span class="sy3">.</span>Raw<span class="sy1">(</span>
&nbsp; &nbsp; &nbsp; &nbsp; fmt<span class="sy3">.</span>Sprintf<span class="sy1">(</span><span class="st0">&quot;SELECT COUNT(*) FROM %s WHERE %s = ?&quot;</span><span class="sy1">,</span> table<span class="sy1">,</span> column<span class="sy1">),</span>
&nbsp; &nbsp; &nbsp; &nbsp; value<span class="sy1">,</span>
&nbsp; &nbsp; <span class="sy1">)</span><span class="sy3">.</span>Scan<span class="sy1">(</span>&amp;result<span class="sy1">)</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> result &gt; <span class="nu0">0</span>
<span class="sy1">}</span></pre></td></tr></table></div></td></tr></tbody></table></div>Регистрирую новое правило:<br />
<div class="codeblock"><table class="go"><thead><tr><td colspan="2" id="772113001"  class="head">Go</td></tr></thead><tbody><tr class="li1"><td><div id="772113001" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">validatorInstance <span class="sy2">:=</span> validator<span class="sy3">.</span><span class="me1">New</span><span class="sy1">()</span>
validatorInstance<span class="sy3">.</span><span class="me1">RegisterValidation</span><span class="sy1">(</span><span class="st0">&quot;exists&quot;</span><span class="sy1">,</span> validators<span class="sy3">.</span><span class="me1">Exists</span><span class="sy1">)</span></pre></td></tr></table></div></td></tr></tbody></table></div>Возможные примеры использования:<br />
<div class="codeblock"><table class="go"><thead><tr><td colspan="2" id="68258882"  class="head">Go</td></tr></thead><tbody><tr class="li1"><td><div id="68258882" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="kw1">type</span> UpdateEntityRequest <span class="kw4">struct</span> <span class="sy1">{</span>
&nbsp; &nbsp; Id &nbsp;<span class="kw4">int</span> &nbsp;<span class="co2">`json:&quot;id&quot; validate:&quot;omitempty,exists=entities&quot;`</span> <span class="co1">//в таблице entities должна найтись запись с таким же id</span>
<span class="sy1">}</span>
&nbsp;
<span class="kw1">type</span> SomeRequest <span class="kw4">struct</span> <span class="sy1">{</span>
&nbsp; &nbsp; Name &nbsp;<span class="kw4">string</span> &nbsp;<span class="co2">`json:&quot;name&quot; validate:&quot;exists=users.name&quot;`</span> <span class="co1">//в таблице users должна найтись запись с таким же name</span>
<span class="sy1">}</span></pre></td></tr></table></div></td></tr></tbody></table></div>По поводу реализации. Для транзакций с БД использую Gorm, и <code class="inlinecode">db.Database</code> в 29 строчке имеет тип <code class="inlinecode">*gorm.DB</code>. Возможно есть более канонический способ динамического построения запроса на основе имени таблицы и имени столбца; но в любом случае об инъекциях речи все равно не идет, так как эти два параметра задаются разработчиком (который при этом легко может поломать запрос, что я как-то раз и сделал, добавив лишний символ <code class="inlinecode">;</code> в struct tag)... Также можно было бы добавить обработку ошибки запроса, но вроде не критично, так как в случае неудачи паники все равно не возникает, а функция просто возвращает false.<br />
<br />
Это я к тому, что напиание кастомных правил валидации - плодотворная затея, может упростить жизнь. И при написании таких функций имхо полезно ориентироваться  на реализации встроенных (baked in) правил в исходном коде пакета.</div>

]]></content:encoded>
			<dc:creator>DrType</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/1501512/8381.html</guid>
		</item>
	</channel>
</rss>
